$mash@bradmash.com: <br/> Software Dev and Music Producer

How Diablo II captivated a generation.

The Diablo II: Lord of Destruction Hero Characters

What was it about Diablo II that captivated an entire generation of pc gamers? Even as of the time of this writing (2019), logging into the U.S. East servers reveal a few thousand active players at any given time, with hundreds of public games to join. Now a legend, Diablo II has become the defining video game to showcase how an action RPG hack ‘n slash is supposed to be done.

Blizzard North

Blizzard North

Blizzard North was originally a third party development team (Condor) and were not originally a “part of the [Blizzard] family” according to Diablo II senior producer Bill Roper. The company was headed by president at the time David Brevik, and vice presidents and brothers Erich Schaefer and Max Schaefer. However, the company was eventually acquired by Blizzard and became known as Blizzard North (as their office resided in northern California). Brevik ran the company from 1993 to 2003, during which time Blizzard North was virtually sovereign from their parent company, Blizzard.

Low Level of Entry

Logitech Mouse

CLICK! CLICK! The average computer user can install Diablo II and start slaying demons. Every action in the game can be accomplished solely with a mouse. The pc hack ‘n slash genre was born with Diablo I, but perfected with Diablo II’s mindless clicking to vanquish demons. According to Roper this was by design to make the Diablo trilogy as accessible as possible to players.

Battle.Net

This is Diablo II’s Battle.net interface.
An improvement over Diablo I’s chunky and dry interface.

Diablo I was released at the end of 1996 and showcased for the first time Battle.net. D1’s interface was clunky compared to its new interface in Diablo II. But at the time of Diablo’s first debut, Battle.net was a hit. Gamers played cooperatively (pve), deathmatch/team deathmatch (pvp), and chat in-game over a standard TCP/IP protocol Blizzard North developed and unleashed Battle.net to the world at the very end of 1996.

Once Battle.net was upgraded with Diablo II, all hell broke loose. A clean way to find, create, and search for public and private games made the online community surge.

According to Roper, the idea for Battle.Net came about in E3 of 1996 and a ton of work went into perfecting Battle.net both from its inception, and its later update with Diablo II.

Gameplay & Story

Diablo has always put an emphasis on developing its story through gameplay. Diablo II’s gameplay and story has been enhanced by its state of the art (at least for the time) integrated cinematics. Showing the wandering traveler on his journey against the Prime Evils.

Diablo put the emphasis on the player to develop their hero character in every respect. Taking a metric ton of elements from Dungeons & Dragons, the player had a few options when it came to developing their character. As one would advance in the game, their character would level up. As their character would level up, stat points and skill points were allotted to the player to spend for reaching their new rank. This allowed the player to “build” their character.

The Classes

Diablo 2 Characters

Rather than get lost in details, I recommend just picking up a copy of Diablo II with the expansion (Lord of Destruction) and playing the game. Diablo II came with 5 playable character classes (Paladin, Barbarian, Necromancer, Sorceress, and Amazon), and two additional character classes in the Lord of Destruction expansion (Assassin and Druid).

Necromancer in Diablo II
A necromancer in Diablo II showing off his legion army of skeleton warriors.

As time went on, various “builds” started to become popular. The amount of builds on the internet were in the hundreds and possibly thousands, some cookie cutter, while other builds where experimental in nature. Diablo II perfected giving the player enough choice so that decisions actually mattered, but enough limitation so that the player could always see direction with their build.

The Loot

Diablo 2 Loot

Players would grind for hours to level their character. But with the grind came loot. Diablo II’s loot system was implemented with granularity in respect to how often certain items and types of items would drop, which enemy types could drop certain types of items, which locations could drop which items as well as other factors such as the players current “magic find” attribute value. The higher a player’s “magic find”(mf for short) the higher chance they had at finding better items.

In Diablo II, players who joined public games via the Battle.net service, would find that fast clicking paid off when it came to snatching loot. Unlike many arpg’s and mmo’s today, when loot “dropped” it was first come first serve. In other words, if an item dropped on the ground, whoever picked the item up first got the item and the other players were out of luck.

This type of loot system arched Diablo II’s player community to be somewhat stingy. People would steal items, and generally it was a good idea to not trust anyone on battlenet unless you actually knew them in real life, or had played with them for an extended period of time (months to years).

Runewords

With the expansion Lord of Destruction came runewords. Items which were socketed could have runes injected into them. If runes of specific types were put into socketable items, in specific orders, runewords would be created.

Ebotdz Runeword

Recipes were a source of mystery, but to the general public’s knowledge, all runewords have been discovered and cataloged by the writing of this post.

The Secret Cow Level

The legend of the Secret Cow Level is all to familiar to avid fans of Diablo. Just get yourself a Town Portal Tome and Wart’s Leg, and combine the two itemswith the Horadric Cube in Act 1 Rogue Encampment… and slay some cows.

The Secret Cow Level

Conclusion

This article could be quadruple its size and still not cover everything. Many details have been missed in terms of what makes Diablo II such a great video game. However, the intent of this article was to remain as objective as possible. What made Diablo II such a success? Blizzard North, low level of entry, Battle.Net (revamp), the new and refined classes, the new loot, runewords, and the Secret Cow Level (don’t kill the king!).

DOOM Eternal Pre-Release Review

DOOM Eternal Game Artwork

I have played Doom since I was about 5 years old. I can remember sitting on my grandpa’s lap, he would make the doom slayer run and I would do the shooting. Growing up I loved Doom 1 & 2! The second installment (Doom II) in the series is what I played the most growing up. I still occasionally install Doom 1&2 and get my demon slaying on. From what I can tell, DOOM: Eternal is going to be a return to nostalgia, with Hell on Earth crazy as ever. Let’s take a look.

DOOM: Eternal Returns to More Classic Enemies

This may be the most exciting thing about DOOM: Eternal for me. From what I can tell, the Id team is really doing their best to get these models and concepts to feel right. They’re keeping the nostalgia alive by doing their best to stay true to their classic counterparts, but also revamping them to be bigger than life.

Let’s take it from square one. You want a modern take on your early Id Doom days? Let’s compare the new concepts to the models from days of old. However, below is not an exhaustive list of all demons in the game, or even returning demons from 2016 (some from 2016 return with slight modifications, but from my viewpoint did not change enough to warrant mentioning here). All of the below concepts and models are brand new and make a first appearance in DOOM: Eternal

Zombieman

The zombieman is back!

DOOM Eternal Zombie
Top left classic Doom zombie, main image DOOM: Eternal zombie.




Arachnotron

The main difference seems to be the new cannon sitting on top of the Arachnotron.

DOOM Eternal Arachnotron
Bottom right classic Doom II Arachnotron, main image DOOM: Eternal Arachnotron.




Arch-Vile

The arch-vile is back!

DOOM Eternal Arch-Vile
Left classic Doom II Arch-Vile, right DOOM: Eternal Arch-Vile.




Mancubus

The mancubus is back!

DOOM Eternal Mancubus
Top right classic Doom II Mancubus, main image DOOM: Eternal Mancubus.




Pain Elemental

The Pain Elemental is back! Personally, strictly in terms of how this demon was reincarnated, to me, looks seriously awesome!

DOOM II Pain Elemental
Classic Doom II Pain Elemental.
DOOM Eternal Pain Elemental
DOOM: Eternal Pain Elemental.

Final thoughts on Classic Enemy Reintroduction

From what I can see, the five brand new enemies to the new DOOM titles (2016+), as seen above, really look nothing short of amazing. It seems id has really taken time to try and keep the retro-nostalgic feel to these enemies while updating them contextual to DOOM: Eternal. I hope you’re as excited as I am to see these brought back!

DOOM: Eternal Invasion Mode

From what I have seen, not much has been revealed about this play mode. The concept is exactly as it sounds, you can invade the single player campaign of people around the world and try and kill the doom slayer. You can choose between a select demon set. This is a 2 versus 1 style of deathmatch.

If executed well, I think this is a great change to the franchise, and offers players a fresh experience on DOOM multiplayer.

In conclusion, you can at the end of this video if you start the video at 16:40 (I’ve gone ahead and done that for you if you just press play) that two players join before the gameplay footage stops. What a teaser!

DOOM: Eternal Level Design

From what we get in early gameplay footage, it seems that the overall level design for DOOM: Eternal is much more open as compared to the level design in DOOM 2016. The latter did feature open environments, but this seems like a staple in DOOM: Eternal. This probably stems from the fact that it’s set on Earth just as classic Doom II. At the very least, this is evidenced by more vertical mobility in the game, featuring a new grappling hook.

DOOM: Eternal Movement & Grappling Hook

DOOM: Eternal Grappling Hook.
The new grappling hook featured on the the bottom of the double-barrel shotgun (super shotgun).

The grappling hook mechanic in DOOM: Eternal is another staple to the franchise as a whole. The vertical mobility it offers for doom guy to slay enemies are endless. Chaining together grapples can lead to some serious air time! Combined with double jumping and wall climbing, the movement in DOOM is better than ever.

Let’s not forget about the new strafing! The quick strafes that doom guy can now perform look amazing. This will offer players better defense from escaping close calls with enemies. Combined with the other new movement mechanics the overall gameplay in DOOM: Eternal compared to DOOM 2016 will be eons apart from each other.

DOOM: Eternal New Guns and Weapons

We won’t spend time looking at guns that have changed only visually, or that are not totally new to the franchise. With that out of the way, check these out.

DOOM: Eternal – Flamethrower

If they came from Hell, they should feel right at home.

DOOM: Eternal Flamethrower
The Flamethrower.




DOOM: Eternal – Heavy Cannon

Although very similar to DOOM 2016’s heavy assault rifle, it is actually a brand new gun and according to some sources is presumed to replace the heavy assault rifle. There are two additional modes the gun can be used in: “Precision bolt” for sniping; and mini-missiles that alternate when fired off of both sides of the weapon.

DOOM: Eternal Heavy Cannon
The Heavy Cannon.




Doom: Eternal – Doom Blade

Ready for some new and awesome glory kills? Then get ready for the doom blade.

DOOM: Eternal Doom Blade
The doom blade.




DOOM: Eternal – Shotgun

Alright, so… yeah it’s not a new weapon. But what kind of DOOM review doesn’t talk about the shotgun?! The one thing to mention here is that in DOOM: Eternal there is a mode for the shotgun that makes it an automatic weapon. Nuff said.

DOOM: Eternal Shotgun
Long live the shotgun.




DOOM: Eternal – Grenade Launcher

This is a presumption that some sources have talked about but has not yet been confirmed. That is to say, this is not the same weapon as the Rocket Launcher.

Final Thoughts on Teaser Trailers

Having watched the trailers a few times, I just want to play the game. At the beginning of this article I mentioned that my favorite Doom game ever is Doom II: Hell on Earth. Knowing that this is the second DOOM game in the new revamped DOOM titles… it makes me smile knowing it takes place on Earth. Just as Doom II: Hell on Earth was Doom I with more content, it seems like DOOM: Eternal is DOOM 2016 with more content, and I’m totally okay with that. The music still sounds great from what we hear in the trailers – thank you Mick Gordon. Speaking of Mick Gordon, if you missed this great GDC talk he gave on how he made the original music for DOOM 2016 you should check it out.

Mick Gordon, music producer for DOOM 2016 talks about how he worked on the project.

It seems to me that this installment, like the last, would make the 90’s id team proud. I can see John Romero and John Carmack smiling at its release, although Carmack will likely not say a word about the release ( https://arstechnica.com/tech-policy/2017/03/john-carmack-zenimax-owes-me-22-5m-as-part-of-2009-id-software-deal/ ). It will be interesting to see if the others comment on it. Romero on the other hand is a vocal dude, and was for DOOM 2016, which I don’t really see changing for this release.

Official DOOM: Eternal Story Trailer E3 2019

Your thoughts?

What are your thoughts on DOOM: Eternal up to this point? What excites you the most about this upcoming release? How do you see this release comparing with the last? What are your thoughts on the Invasion multiplayer mode? Let me know your thoughts in the comments!

Drupal 8 theme: How to develop a custom theme.

Drupal 8 Logo

Whatever your use case is for developing a custom theme in Drupal 8, the PHP Symfony, Twig, and markup goodness Drupal 8 offers developers is great. Let’s cut to the chase and get started.

You can easily scaffold a theme using drupal console with the drupal generate:theme [options] command found at https://hechoendrupal.gitbooks.io/drupal-console/en/commands/generate-theme.html. In this guide, we will be creating a custom Drupal 8, manually generating the files as they are needed. However, do not overlook this command for future use. After you go through this guide and understand what composes a theme, I recommend for future projects using this command.

In this how-to tutorial we will take the example of https://artist.camp and the custom theme implemented on that site.

Create a Drupal 8 theme directory.

The first thing you will need to do is create a directory for your theme. Generally speaking, best practice is to create the directory structure as follows: docroot/themes/custom/YOURTHEMENAME

In this example, we will name our theme directory as docroot/themes/custom/artistCamp

A quick note on yml files.

Anytime you see indentation in yml files, the indentation are important and are only 2 spaces. That is to say, if something is indented twice, it equates to 4 spaces. Improper indentation of yml files will make things not work properly. And generally speaking, improper syntax at all will break things.

*.info.yml

This file is required. Once you have your theme directory created, you will need to create the *.info.yml file. In our case, we will name this file artistCamp.info.yml. This file is a configuration file which will register our theme with our Drupal 8 install. In this file there are a few required key/value pairs as well as many optional key/value pairs that we define as metadata to describe our theme.

Required *.info.yml key/value pairs.

The required keys are name, type, and core. For our example we will define a few other useful keys. Below you will see the contents of artistCamp.info.yml.

*.info.yml file used for registering your Drupal 8 theme with the system.

Some of the keys are self-evident such as “description” but let’s elaborate on a few of the other keys.

base theme: Your theme can derive from another theme and according to drupal.org:

“Sub-themes are just like any other theme, with one difference: they inherit the parent theme’s resources. There are no limits on the chaining capabilities connecting sub-themes to their parents. A sub-theme can be a child of another sub-theme, and it can be branched and organized however you see fit. This is what gives sub-themes great potential.”

screenshot: The “Appearance” admin user-interface (/admin/appearance), when you are selecting a theme to use for your website, will show the image you specify via the path provided to the screenshot key.

regions: This is very important metadata that creates reference-able regions that will become the main parts/sections of your theme. Each region renders as its own encapsulated black box. Regions are reference-able via their unique hook. These hooks are essentially IDs that reference your regions for theming and pre-processing. More on this later. The Structure -> Block Layout admin user-interface displays the custom regions you define, so that administrators can add blocks to those regions as needed.

libraries: A reference to a defined Drupal 8 “library” (that is defined in *.libraries.yml more on this later) applied to every node (in Drupal jargin a node is a page) using this theme.

*.theme

Include a theme as it is best practice to have one. If you create it blank, make sure to at least include the <?php at the top of the file, and including a comment like /* Stub */ may be nice as well.

This file allows you to implement a list of life-cycle hook functions associated with your theme such as HOOK_preprocess_page. There are a plethora of contextual hooks you can implement, of which you can check out on the drupal.org website. However, for this file, if we were to implement HOOK_preprocess_page for the artistCamp example, the function name would be, artistCamp_preprocess_page. This function allows us to prepare variables for the page.html.twig file. Drupal inherently knows when to run this function. The equivocation of this function prepares our variables for the page.html.twig template to use. Drupal 8 accomplishes this with its event system runs implemented life-cycle hooks at the proper times.

Preprocessing Drupal 8 theme variables.

As we saw in page.html.twig, our Twig templates can be passed preprocessed variables. That is to say, any Twig template can have custom, defined variables at their disposal if we set them up properly, one way being through preprocess functions. Let’s take a look at the artistCamp_preprocess_page function defined in the artistCamp.theme file.

hook_preprocess_page function used for preparing variables for use in your Drupal 8 theme twig templates.

It is worth noting before commenting on the above function definition that to create custom variables for use in Twig templates via their preprocess function counter-part, that you create them in the following format:

$variables['foo'] = "bar";

So, we create a custom variable called ‘current_route’ to use in the artistCamp page.html.twig template. The route the current user is requesting becomes the value of ‘current_route’. This function only runs on nodes that use the page.html.twig template, which, for most sites, will be used on every page.

Next we will look at the html.html.twig file, however I would urge you quickly scroll past it and look at the page.html.twig file to fully follow this example. To clarify, the ‘current_route’ variable determines the markup generated to the client requesting the web page. I recommend to still read the html.html.twig section.

html.html.twig

This twig template serves as the entry point for ultimately rendering all of your templates. It always runs on page loads that are uncached. Let’s take a look at the artistCamp html.html.twig file.

<?php
{#
/**
* @author Brad Mash, Software Engineer
* @file
* Theme override for the basic structure of a single Drupal page.
*
* Variables:
* - logged_in: A flag indicating if user is logged in.
* - root_path: The root path of the current page (e.g., node, admin, user).
* - node_type: The content type for the current node, if the page is a node.
* - head_title: List of text elements that make up the head_title variable.
*   May contain one or more of the following:
*   - title: The title of the page.
*   - name: The name of the site.
*   - slogan: The slogan of the site.
* - page_top: Initial rendered markup. This should be printed before 'page'.
* - page: The rendered page markup.
* - page_bottom: Closing rendered markup. This variable should be printed after
*   'page'.
* - db_offline: A flag indicating if the database is offline.
* - placeholder_token: The token for generating head, css, js and js-bottom
*   placeholders.
*
* @see template_preprocess_html()
*/
#}
{%
set body_classes = [
logged_in ? 'user-logged-in',
not root_path ? 'path-frontpage' : 'path-' ~ root_path|clean_class,
node_type ? 'page-node-type-' ~ node_type|clean_class,
db_offline ? 'db-offline',
'no-js'
]
%}

{{attach_library('artistCamp/global-header')}}
{{attach_library('artistCamp/global-footer')}}

{% set frontClass = ""  %}
{% if current_route == "view.frontpage.page_1"  %}
{% set frontClass = "frontpage" %}
{% endif %}

<!DOCTYPE html>
<html{{ html_attributes.setAttribute('class',frontClass) }}>
<head>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());

gtag('config', 'UA-XXXXXXXXX');
</script>

{#
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXXX');</script>
<!-- End Google Tag Manager -->


<link rel="preload" as="script" href="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js">
<script>
(adsbygoogle = window.adsbygoogle || []).push({
google_ad_client: "ca-pub-XXXXXXXXXXXXX",
enable_page_level_ads: true
});
</script>
#}
<head-placeholder token="{{ placeholder_token }}">
<title>{{ head_title|safe_join(' | ')|trim('| ') }}</title>
<css-placeholder token="{{ placeholder_token }}">
<js-placeholder token="{{ placeholder_token }}">
</head>
<body{{ attributes.addClass(body_classes) }}>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

{#
<section aria-label="Skip to main content.">
#}
{# Using the open source implementation found at: https://accessibility.oit.ncsu.edu/it-accessibility-at-nc-state/developers/accessibility-handbook/mouse-and-keyboard-events/skip-to-main-content/ #}
{#
<a href="#page-instance-fluid" class="skip-main">
{{ 'Skip to main content'|t }}
</a>
</section>
#}
{# Do not remove these three: page_top; page; page_bottom; ever! #}
{{ page_top }}
{{ page }}
{{ page_bottom }}
<js-bottom-placeholder token="{{ placeholder_token }}">
</body>
</html>

You can see that the main HTML elements are here, html, head, body.

Rather than go into great detail about everything going on in this file, we will comment on some high-level things. First notice that we can attach libraries directly to our template with a single twig function:

{{attach_library(‘artistCamp/global-header’)}}

Libraries will be discussed in the *.libraries.yml section below. However, what this is doing is taking all of the resources listed in the ‘artistCamp/global-header’ library (mainly CSS and JavaScript references), packaging them up, and applying them to the final rendered page markup this template produces.

Finally, towards the bottom of the file you will notice the following:

{{ page_top }}
{{ page }}
{{ page_bottom }}

These are variables which reference global parent regions (not the regions we defined, these regions, particularly the page region, hold our custom defined regions we defined in our *.info.yml file). If you’re curious why page_top and page_bottom are not accessible in Block Layout you can see the following link, https://api.drupal.org/api/drupal/core!modules!system!system.module/function/system_system_info_alter/8.2.x. But in short, these are system administered regions.

page.html.twig

If you’re following, you should see that whatever is output via this file will be between the <body>…</body> tag since {{ page}} was output there as we saw when we looked at the html.html.twig file.

This is the default template that all themes use if no other twig template overrides their precedence (more on twig hook theme precedence later). To clarify, if your theme includes all of the files this tutorial has outlined up to this point, as well as this file, this is the file that is basically going to generate all of the markup for your website no matter what page you’re on.

Let’s take a look at the artistCamp page.html.twig file, and keep in mind that we preprocessed this twig template via out *.theme file’s artistCamp_preprocess_page function which made the ‘current_route’ variable available.

<?php
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
{#
    /**
* @author Brad Mash, Software Engineer
* @file
* Artist Camp Theme File
* page.html.twig
* Implements Bootstrap 4.1.x
*/
    #}
    <!-- Artist Camp Developed by Brad Mash. -->
    <div id="global-container" class="global-container">
{% include directory ~ '/templates/includes/header/header.html.twig' %}
<div id="global-content-container">
<div id="content" class="content">
<div class="top-fluid-container">
<div id="top-fluid" class="top-fluid">
{{ page.top_fluid }}
</div>
</div>

{% set containerized_routes = ['user.login', 'user.register', 'node.add','node.add_page','entity.user.edit_form','comment.admin','view.files.page_1','view.message.page_1']  %}
<div id="page-instance-fluid" class="page-instance-fluid">
<main id="main">
{% if current_route in containerized_routes %}
<div class="container">
{{ page.content }}
</div>
{% else %}
{{ page.content }}
{% endif %}
</main>
</div>

<div class="bottom-fluid-container">
<div id="bottom-fluid" class="bottom-fluid">
{{ page.bottom_fluid }}
</div>
</div>
{% include directory ~ '/templates/includes/footer/footer.html.twig' %}
</div>
</div>

{# {% include directory ~ '/templates/includes/footer/footer.html.twig' %} #}
    </div>

Again, rather than comment on every part of the file, let’s consider the more interesting parts. The first thing we want to point out is the use of our custom defined regions such as {{ page.top_fluid }}

If needed can theme the top_fluid region with a twig template. We will not spend time doing this in this tutorial. However, Drupal will provide theme hooks for this region which can be themed and preprocessed as needed.

**Note: This may be a good point in time to say that twig templating in Drupal 8 is very granular in scope. For example, a form on a page can be twig templated and preprocessed. But then, each input of the form themselves can be as well! Twig templating is a game of inception.

Drupal 8 Twig Logic

Next consider this snippet of twig markup found in the artistCamp.page.twig file:

{% set containerized_routes = ['user.login', 'user.register', 'node.add','node.add_page','entity.user.edit_form','comment.admin','view.files.page_1','view.message.page_1']  %}
<div id="page-instance-fluid" class="page-instance-fluid">
<main id="main">
{% if current_route in containerized_routes %}
<div class="container">
{{ page.content }}
</div>
{% else %}
{{ page.content }}
{% endif %}

It’s easy to see we have a small piece of logic that checks our custom defined and available ‘current_route’ variable, and depending on its value either outputs the {{ page.content }} region in a container or not.

Finally it’s worth mentioning that you can include twig templates inside of other twig templates using the following syntax as we see in this file including the footer twig template:

{% include directory ~ '/templates/includes/footer/footer.html.twig' %}

*.libraries.yml

This file contains library definitions which can reference internal and external resources such as CSS and Javascript, and houses those defined resources under a custom name/ID that you choose. Let’s take a look at the artistCamp.libraries.yml file:

#Global for all pages
global-header:
  version: 1.0
  header: true
  css:
    templates/includes/css/global/temp.css: {}
    base:
templates/includes/css/global/base.min.css: { minified: true }
    layout:
templates/includes/css/global/layout.css: { minified: true }
templates/includes/css/global/layout.min.css: { minified: true }
templates/includes/css/bootstrap/bootstrap-grid.min.css: { minified: true }
    component:
templates/includes/css/custom-dropdown-menu.css: {}
https://cdnjs.cloudflare.com/ajax/libs/flickity/2.1.2/flickity.min.css: { minified: true }
https://unpkg.com/ionicons@4.2.2/dist/css/ionicons.min.css: { minified: true }
https://cdnjs.cloudflare.com/ajax/libs/plyr/3.4.6/plyr.css: {}
templates/includes/css/global/component.min.css: { minified: true }
templates/includes/css/global/header.min.css: { minified: true }
templates/includes/css/global/footer.min.css: { minified: true }
https://use.typekit.net/hkv5mea.css: {}
https://fonts/googleapis.com/css?family=Encode+Sans+Condensed: {}
    #theme:
 #templates/includes/css/global/print.css: { media: print }
  js:
    templates/includes/js/custom-dropdown-menu.js: {}
    templates/includes/js/temp.js: { weight: -5, minified: true }
    templates/includes/js/global.min.js: { weight: -5, minified: true }
    https://cdnjs.cloudflare.com/ajax/libs/plyr/3.4.6/plyr.polyfilled.min.js: {minified: true}
    https://cdnjs.cloudflare.com/ajax/libs/flickity/2.1.2/flickity.pkgd.min.js: {minified: true}
  dependencies:
    - core/jquery
    - core/jquery.once

global-footer:
  js:
    templates/includes/js/custom-plyr-implementation.js: {}

404:
  version: 2.1
  header: true
  css:
    component:
templates/includes/css/global/404.min.css: {}

If you recall, in the html.html.twig file we had:

{{attach_library('artistCamp/global-header')}}
{{attach_library('artistCamp/global-footer')}}

These two lines applied the resources defined in the libraries file to our template, and ultimately applies them to all rendered pages.

Advanced Theming

As mentioned in this tutorial, theming in Drupal 8 is very granular. That is to say, virtually any component on your webpage not only is likely theme-able, but will have dedicated theme hook names (suggestions) associated with it so that you can implement the proper files to target that component. If you have twig debugging turned on for you site, you can go to any page in your site, open developer tools, and in the markup HTML comments will be present that show you the twig theme suggestions. To clarify, this means that if you need to theme or preprocess a particular component the HTML comment will basically tell you what file you need to create so that you can target the component in question. Read more on this topic at https://www.drupal.org/docs/8/theming/twig/debugging-twig-templates.

Conclusion

Once you have implemented these files, you can go to yoursite.com/admin/appearance and install and set your theme as active.

Primordia Review: Why you should play it.

Primordia banner image, official logo.

Looking for a new video game to get sucked into? If you’re a fan of story driven games, sci-fi, interesting artwork, and atmospheric music look no further! Although relatively speaking Primordia is an older title by today’s standards (released originally in 2012), I believe it didn’t get the attention it deserved. I don’t blame the gaming communities at large though, it’s definitely a niche genre of video games – point and click.

However this may be perceived, it doesn’t really feel like a point and click. Well, maybe it does, but I guess the point is the game is so engaging and interesting that you don’t mind that you are mindless pointing and clicking all over the place to progress.

Horatio (left), Crispin (Right)
Horatio (left), Crispin (Right)

The Primordia World

Set in a post-apocalyptic world, you play as Horatio Nullbuilt a robot who has crashed his ship on a desert planet inhabited by other robots. Horatio is not lonely on his adventure to fix his ship, he is accompanied by his pesky companion Crispin Horatiobuilt.

As the two explore the world, it becomes obvious fairly early in the game that Horatio is fascinated with “Man”. Horatio has a copy of the Book of Man, which to Horatio is everything including divine in a sense. The beginning passage reads:

In the beginning, all was still and silent. Then, Man the All-Builder spoke Word, and the Word begat the Code, and so the world began to spin. Thus dawned the Primordium, the first age, the age of building.

The Book of Man
The Book of Man

Primordia Game Mechanics

The main mechanics of the game are world exploration, crafting, and puzzle solving. The items you find in the game each have pre-determined usage, but figuring out how to use your items, how to craft what you need for any given job makes you feel like a genius. As a programmer by profession, the puzzles make me smile as they are realistic and grounded in real-world mechanics, ideas, and logic. Many of the puzzles do not have simple solutions either. And map reuse is a key part of the game. Obtain one item at X, travel back to W, before going to Y. I honestly wrote some things down to better manage what I had going on in the game (mainly numbers for key codes and such).

Metropol

Final Remarks

The world is believable and enthralling as you embark to uncover the darker places in search of the energy power source you need to leave this crazy place. Eventually your journey will lead you to the city of Metropol where Horatio and Crispin fight for their very lives.

Compared to other games in the same vain such as Beneath a Steel Sky and Machinarium, Primordia offers an amazing and rememberable experience which is why you should play Primordia.

Why Node Will Win Over Java

Node JS and Java

I’ll preface this article with saying that I have nothing personally against Java. And honestly, I don’t think it’s a bad language to build apps in.

Now that is out of the way, I’ll explain why Node will end up winning over Java, at least for corporate web application development. To clarify and stress, Java generally has good performance if your programmers know what they’re doing, is easy to learn, and can scale as needed with proper implementations.

However, Node.js generally has these things going for it as well. And although different stress tests could avail different statistics of each platform, the great thing about Node.js in terms of building web applications is the asynchronous architecture of its run-time environment.

Although Node.js has threads for I/O operations, the runtime environment is architected as an event loop rather than some complicated system of managing threads. It does manage threads, but it’s as simple as having the event loop running – that’s it. As applications become more intensive on I/O operations, companies will need better performance in this area, and this is where Node.js shines. Why? To reiterate, if your web application is just responding to requests and performing general I/O then all of these requests can be handled asynchronously by Node.js by it’s very nature. You don’t have to do anything extra. You don’t have to include libraries to make this magic happen for you. The system itself is built to highly optimize these types of operations.

How long this evolution will take is hard to say. I’m a realist, so I’m not saying this is an overnight event, or a ten year transition. This could take thirty years, and probably will take closer to one hundred years. I think Java is the next COBOL, by and large companies aren’t selecting COBOL as their language/platform of choice when a web application is in mind. But, COBOL has been around because it is performant and was highly used for a number of years. The same will be true of Java.

So to try and make my prophecy more specific I will leave on this note. The argument could be made about any language given enough time. However, it seems to me that if trends continue the way I believe they will, Node.js will grow as a platform and community at a rate consistent and parallel to the rate of growth Java is abandoned at least for a substantial period of time.

Who I Am

Brad and Tiffany Mash
My wife Tiffany (right), and me (Brad) left.

Hey there!

If you’re here I don’t know why, but thank you for checking the blog out! This is just a personal blog where I share all types of things like personal projects, and honestly some pretty random content from time to time.

So who am I?

This is an interesting question for many reasons. I’m a father to my son; husband to my wife, son to my parents, grandson to my grandparents. Catch the drift?

I grew up in Athens, Ohio (USA) and lived there my entire life until I moved to Lancaster, Ohio (USA) when I was 27. Athens is a fairly small town, but a college town, home of the Ohio University Bobcats. It was a great place to grow up. There’s not much here besides the college so I won’t bore you.

I’m a recent father to this little booger.

My son, Rowan
My son, Rowan

It’s a blast! Seeing him grow and learn is the greatest thing I have experienced.

I could go on and on about my family. My wife is also… AWESOME. She’s the best.

Not to downplay my family, because they’re great, and the best part of my life. But, who am I outside of a family man?

Well, I write software. Specifically since 2010 I have worked at Ohio University in some capacity writing code and building webapps and web interfaces. In 2010 I was hired as a Student Web Developer, until 2013 when I was hired full time as a Web Developer. I worked that job, which developed passion for writing software, for six years. So from 2010 until May 1st of 2019 I was a web developer. I have recently changed positions at OU and now work on the software engineering team as a Software Engineer II writing angular, node, java, and grails applications.

WUSOC Building, the building I work in.
The building I work in.

I haven’t even began to answer the question though!

I’m also a musician of 15 years. So let’s see I’m 28 now (as of this writing), minus 15, so 13! Now I guess you could say but Brad, you took piano lessons before that, those count. Eh, not really in my opinion. I wasn’t a musician, but rather a copy cat. For a period of time I really did enjoy piano lessons as a kid. My teacher Gary Alton is a great guy, and a virtuoso. This kat hand writes his own pieces in notation form, and they’re equally beautiful as they are impressive.

Gary Alton
This is Gary.

So yeah, the piano lessons eventually stopped somewhere around 11 years old. But I grew up around music. My grandfather has had a recording studio he built over the years, for at least the past 20 years. At one point he hosted a local radio show called Hometown Showcase where local talent would be brought into the studio to perform and be played on radio. My grandfather (Ron Mash) and his recording engineer Dave Norris would interview the musicians and bands over the course of a 2 to 3 hour show. I would just sit in the control room, or in the recording room and just listen and soak everything in. Years of this really had an effect on me. After the first year, at the age of 13 I began to learn how to play the guitar.

My grandpa, Ron Mash in the studio playing his Gibson Star acoustic.

The following years, so we’ll say 13 – 18, literally were filled with two things: playing guitar whether by myself or jamming with people; and Diablo II.

The Diablo II logo, which is forever burned into my conscious. I can still hear the song that plays on startup of the game. duuuuun duuuuun dun DUN DUN!

Oh my… Diablo II. Let’s just say it was an addiction. Quite honestly it was an addiction. I mean I had no responsibilities, or real responsibilities other than going to school and doing my homework. I had chores like weed eating, but all kids have chores. The amount of time completely wasted playing that game is sad the more I think about it. But at the time I had a ton of fun, and didn’t know better. It’s part of my life, I’m not going to just forget it or erase it.

Skater dude.

Me back in high school skating our local skate park.

I think the following facebook comment from my grandmother sums up the rest of my thoughts on this phase of my life.

A facebook comment from Brad Mash's grandmother on the picture of him when he was younger skating at the local skatepark which reads, "I am glad you are out of that faze."
Me too grandma, me too.

Towards the end of my high school career, actually I believe my senior year, I started golfing. And that whole year, I golfed just about every weekend that wasn’t bad weather with my cousin Mike.

Mike (Brad's cousin who he golfed with) and his family.
Left Mike, Right Lacey Mike’s wife, kid in stroller Davis (their son).

I mean hey, we golfed for a year. There’s not a whole lot to elaborate on there. But I will give you one story from our golfing adventures… and it may just be the time Mike and I went golfing together for the first time. To start, let me preface this by saying before Mike and I started golfing together, we didn’t really have much golfing experience – if any. So we show up at the Forest Hills Golf Course ready to begin our adventure.

The owners of Forest Hills Golf Course.
The owners of Forest Hills Golf Course.

Now I can’t remember their names, but in the picture above, the two younger gentleman ran the golf course. And depending on the day, usually just one of them were there. They’re both great dudes, and for that year, we became pretty good friends. But it wasn’t always that way…

We get out of the car and walk in the main office building for the course. I’m fairly certain at this point we didn’t have clubs, at least I know I didn’t because I can remember renting clubs. So we get the clubs, talk to the guy running the course for a few minutes, and he tells us to enjoy ourselves.

We walk outside. Where… do we tee off? Now, if you know Mike and myself, we are not the prideful type. And to be clear, we honestly thought we were teeing off at the correct location. We put our tees into the ground, and swing. Well, one of us took a big ole chunk of dirt and grass out of the ground and it went flying. Whatever, that happens. Before we know it the owner guy runs out of the office yelling and was royally ticked! “What the f*** are you two doing?! You tee off down there you stupid f***s!” Oh. So yeah, that’s the story of the time we tee’d off at the practice put area.

So in the timeline of my life, that puts me up to college. Honestly college was pretty straight forward for me. I worked (a job) through college, so I completed my degree in 5 years as opposed to 4 years. I graduated with a Bachelor of Specialized Studies in Computer Science and Communication Studies.

Ohio University's Academic Research Building where I spent many nights working on projects.
Ohio University’s Academic Research Building where I spent many nights working on projects.

All that means is that instead of taking a predefined degree of coursework, I decided I wanted to create my own degree. And as awesome as it sounds, and it is, it was somewhat of a complicated process. I had to have two administrators in each field (computer science, and communication studies) be my mentor/advisor. These two mentors helped me define my coursework (the classes which would compose my degree) and signed off on the coursework. David Juedes, Ph.D. is a tenured associate professor and chair of the School of Electrical Engineering and Computer Science and was my mentor for the Computer Science part of my degree (he taught parallel programming which was an awesome class).

Dr. David Juedes.
Dr. David Juedes, my former Computer Science mentor and adviser.

And Dr. Tom Davis who held a number of high-level positions at the university working in the office of Advancement and worked as a dean.

Dr. Tom Davis my former Communication Studies mentor and adviser.

During my college years, and I even remember where, I heard deadmau5’s music the for the time. It was sometime in 2014 in my office cube. Ah, and if you have been following dates, because yes I finished my degree in 2014, I was hired full-time in 2013 at Ohio University as a web developer. So working a full time job and going to school was, we’ll say, fun. But that’s not the point! So I was sitting in my cube one day and someone was like hey you can grab a copy of deadmau5’s 4×4=12 album for free today on Google Play! Uh, deadmau5? I mean to my credit, I had listened to electronic music before, but it wasn’t my go-to genre of music listening at this point.

The album cover of deadmau5's 4x4=12 album.
The album cover of deadmau5’s 4×4=12 album.

It’s still my favorite electronic album. Having grown up around music, I hadn’t heard this type of music before. I mean, yeah, house music I had heard, but not like this. I mean love or hate Joel, you have to give him credit, his music is very well produced.

By this point I was slowly putting together a small studio of my own. But, all I knew was after I heard that album for the first time, I fell in love with electronic music, and started learning how to produce it. Now what’s funny is sometime before this the year prior I had downloaded a copy of Reaper (a digital audio workstation, or DAW for short). This is a program that let’s you create music like you would with a professional recording studio, but rather via software instead of physical gear. I played around with it. Now, after the revelation of deadmau5 I really began listening to a lot of other electronic music. But sometime in 2014 I decided I needed a better suited DAW so that I could really begin experimenting making electronic music.

Cubase 7

Enter the world of Cubase. Cubase is just one of the many DAWs on the market. And quite honestly, when I picked Cubase from the plethora of choices out there it wasn’t based on anything other than my own research. I guess what I’m trying to say is that when I started with Cubase, there really wasn’t any real reason why I went with it. I just knew Reaper wasn’t for me.

After nearly three years of work I was finally finished with my first album. I won’t link all of my work here, as there is no real reason to do that. But, below is the first album I produced and released on YouTube in December of 2016 under the alias forrest MASH entitled Lost Without A Shepherd.

My first album released under the alias forrest MASH entitled Lost Without A Shepherd.

Since the release of that first project I have released 4 albums and two EPs under forrest MASH, all of which are on YouTube. I’ve also got another alias as Futzsyn that I’m experimenting with but we’ll see if it continues or not.

As of the time of this writing I’m announcing today that I am going to be starting my fifth studio album titled Where Are We Going?

You know as I wrote this I had to pull out the events and highlights of my life that help define who I am. There’s a lot left out, and that’s okay. I guess I will leave this off with why I am starting this blog. There are two reasons. One, the only life skill I have is being good with computers. I know how to program. That’s pretty much the only marketable skill I have. So this site will serve, somehow, as a reflection of that. Not that I care to flaunt it, that’s not my point. But hey, right now I’m still a working man and this site could become a resume builder let’s be honest.

And lastly, I hope to just share stuff. I’m sure I’ll be sharing musical projects on here, and I hope they gain viewership. And not for the numbers. I could care less about numbers for numbers sake. But for community. For the love of music. For creativity. For people.