Simple Megamenu Bonus

New Drupal Modules - 9 November 2017 - 7:08am

Simple Megamenu Bonus extends the great Simple Megamenu Module by @flocondetoile

Special thanks to @flocondetoile!
If he likes the concept of these extensions we'd be happy to integrate this module into simple_megamenu one day. Otherwise this should be seen as a nice option for your special use-case. Simply read on...

Categories: Drupal

Empires Now Available From WizKids

Tabletop Gaming News - 9 November 2017 - 7:00am
It’s the 18th century and the time of conquest is upon us. Countries like Spain, Russia, France, and Great Britain are sending out explorers to far-flung reaches, claiming land in their name. The race is on to grow the most grand empire in all the world. And that’s what you’ll be doing as the head […]
Categories: Game Theory & Design

Orwell was released... and the world changed - by Melanie Taylor Blogs - 9 November 2017 - 6:53am
In the first of a series of blog posts on Orwell: Ignorance is Strength, we take a look at how things have changed since the release of Orwell: Keeping an Eye on You, and the substantial impact of those changes on the game, our studio, and the world.
Categories: Game Theory & Design

Level Design First Blocks: Part 2 – Level Design Theory - by Max Pears Blogs - 9 November 2017 - 6:50am
This is the second part of my three part series where I discuss some of the best practices to think about when making levels. These are guidelines which will help shape your levels and take them to the next "Level" ....aha puns
Categories: Game Theory & Design

25 Best Metrics to Help You Track User Loyalty - by Vasiliy Sabirov Blogs - 9 November 2017 - 6:50am
Measuring user loyalty remains one of the most important questions for product’s success. Let's see all the major metrics that you need to know to calculate your user loyalty.
Categories: Game Theory & Design

The “skip button” dilemma - by Sergio Rosa Blogs - 9 November 2017 - 6:50am
Why do some have problems with a "skip boss" button or "exploration mode" but, at the same time, consider unskippable cutscenes/dialogues a design flaw? Could it be that gameplay and story are not working together to deliver a cohesive experience?
Categories: Game Theory & Design

6 Reasons Improbable's SpatialOS isn't ready for Virtual Reality - by Carleton DiLeo Blogs - 9 November 2017 - 6:49am
VR development on SpatialOS isn't easy so I decided to create a short write up about the main problems I've faced.
Categories: Game Theory & Design

Slow-mo Tips And Tricks - by Megan Fox Blogs - 9 November 2017 - 6:48am
Ever wanted cool slow-mo pulses in your game? Ever wanted to let your player run around at full-speed while the rest of the game is in slow-mo? Read on!
Categories: Game Theory & Design

Preparing For & Surviving Gaming Expos As An Indie - A PAX Aus Post Mortem - by Meredith Hall Blogs - 9 November 2017 - 6:48am
My name is Meredith. I’m the Producer at Ultimerse, a virtual reality company in Melbourne, Australia. We just exhibited at PAX AUS for the very first time, and there are a million things I wish I’d known - here are just a few of them.
Categories: Game Theory & Design

The Growth in Norwegian Game Studios - by Dylan Moran Blogs - 9 November 2017 - 6:47am
The Norwegian gaming industry has achieved a lot more than the targets.
Categories: Game Theory & Design

Mindjammer: Children of Orion—the Venu Sourcebook

New RPG Product Reviews - 9 November 2017 - 6:38am
Publisher: Modiphius
Rating: 5
Does the Commonality cloy a bit? Or do you want to get to know the 'opposition' so as better to defeat them? The Venu are the 'bad guys' of this setting, being a cruel and oppressive civilisation that are the diametric opposite of what the Commonality stands for and strives for. Of course, there are opportunities there too...

The Introduction explains how the Venu can be seen as what Earth's civilisation might have become had they chosen a different path. They left very early on, maybe eight thousand years ago or more and have been treading their own road ever since. The present Venu aren't that old, because they destroyed themselves fighting one another - this Venu civilisation is at most fifteen hundred years old, having built itself up on the ruins of more ancient ones. They are a rich and complex society, and this book attempts to present them - warts and all - with the aim of providing resources for adventuring in Venu space, creating meaningful Venu NPCs as adversaries (or allies?), and maybe even playing the odd Venu character.

Chapter 2: History and Prehistory goes into detail on the real history of the Venu. Most if not all of the present-day Venu don't know about it, as that apocalyptic war fifteen hundred years ago wiped out most of what went before, and the time since has been one of oppression, false news, and lies masquerading as the truth. It all began with the first ship using stasis technology to leave Earth. Heading for the Orion Nebula, their intended destination turned out to be unsuitable for habitation but fortunately they found a nearby world on which to settle. It wasn't ideal and after some struggles a major terraforming plan was put into action. They'd been there almost a thousand years before a message from Earth arrived... by then they'd almost forgotten where they came from and it was a decided shock to hear a planet on the other side of the galaxy claimed to be their origin. Even more, technology on Earth had advanced far more than theirs, and the information transmitted enabled the recipients to gain ascendancy over the rest of the planet, leading to a three thousand year long golden age. Then a second message came, reflecting further changes on Earth and again sending the Venu into a tailspin. Some accepted what they were told, others refuted it, nobody would agree to differ and it all ended in tears... and apocalyptic war!

From the shattered remnants left by that war arose the immortal God-Emperor Venu. Forty generations later, his followers the Pure hold true to his Tech Commandments, building their world as directed. And then the Commonality came, a real cat amongst the pigeons. The God-Emperor broke a long silence to issue more edicts, the New Pronoucements, and now leads his people in war against the Commonality seeking to defeat their 'lies' and embrace something called the Radiant Darkness, a relgion seemingly cooked up for the purpose, having consolidated his hold on surrounding worlds and colonies seeded before all the unpleasantness happened and contact lost.

Scene set, we then begin to find out about the Venu people themselves in the next chapter. They seem to be a surprisingly uniform bunch, tending to dark hair and skin, but more worryingly, in their behaviour too. Society is very conformist (at least in part out of fear) and hierarchical. Technology is prolific yet subject to myriad rules and restrictions, for example travel permits are required even to move about your own city let alone travel to another planet.

Chapter 4: The Venu Empire starts by looking at the political hierarchy with the God-Emperor at the top assisted by fifteen Lords Countenant who each head one of the government departments or commissariats. They deal with nearly every aspect of life - it's quite hard to do anything at all without their influence being felt. The majority of the population are the Pure, the obedient masses. There is great fear and hatred of so-called Abominations; mutants in other words. With loads of detail to bulk this out, there are also plot seeds scattered throughout. Chapter 5 continues this background information by looking at the Dark Radiance... but just what is this? It hovers somewhere between a religion and a personality cult, centred of course on the God-Emperor himself. It's of particular interest because it appears to confer certain powers on those it mutates. Those mutated by Dark Radiance are not ostracised like other mutants, rather they are regarded as favoured or blessed. Chapter 6 then explores Venu technology, something they are ambivalent about. The society is anti-intellectual, yet they realise that they need tech to survive and prosper. This results in most people having little understanding of the technology that they use, often with disasterous results. The chapter contains an extensive catalogue of equipment.

Moving on, Chapter 7: Starships and Space Travel reveals that Venu space technology is somewhat behind that of the Commonality. The classes and deployment of military vessels are discussed here, as well as civilian ships - there are even a few deckplans. Ships sorted, we go on in Chapter 8 to explore Venu Space, beginning with the homeworld, Venu Prime and including detailed instructions for designing your own worlds. There are plenty of examples of solar systems in Venu space to visit as well.

After what seems to be quite a massive information dump - fascinating stuff, it's taken me ages to read and I've enjoyed every word! - we move on to more game-mechanical stuff with Chapter 9: Creating Venu Characters. Whether or not you are willing to let your players be Venu depends on the game you want to run, but it's useful to be able to create detailed antagonists anyway. There are a range of different cultures, genotypes and careers to choose from. Then it's time to look at Chapter 9: Venu Adversaries, which provides an array of ready-made 'bad guys' to throw in the party's path. There's a bestiary here too.

Finally, Chapter 11: Venu Campaigns looks at the vast variety of things you can do in Venu space now that you know about it. Perhaps the party are Venu, and options range from Imperial intrigue to trying to discover what Dark Radiance actually is, or perhaps formenting a rebellion against a repressive society. On the other hand they might be Commonality - spying, perhaps, or out to wreak havoc amongst their enemy. There are plenty of ideas thrown out in a sentence or two... but like most everything else in this book, you will need to put in some work to actually use it in your game.

A fantastic overview of a major player in galactic space, which really gives a good feel for and understanding of what to the Commonality are bogey men. There's too much that isn't for player eyes to make it a useful book for the whole group - even if they are playing Venu - so be prepared to explain a lot! Definitely a useful addition exploring this whole new region of space and its inhabitants, an addition to the setting capable of being used in many differnt ways.
Categories: Game Theory & Design

Worldbuilding With NPC Dialogue: A Beginner's Guide - by Natalie Mikkelson Blogs - 9 November 2017 - 6:23am
How to breathe life into an open world game using non-narrative dialogue.
Categories: Game Theory & Design

Asmodee Launches Holiday Sale

Tabletop Gaming News - 9 November 2017 - 6:00am
So, it’s come to this… We all knew they’d show up eventually. Well, they’re here. Asmodee looks to be leading the group, having launched their Holiday sale. And, being Asmodee, it’s not just them, but all their subsidiaries like Z-Man, Fantasy Flight, Days of Wonder, and others. And, you know, I’m a big fan of […]
Categories: Game Theory & Design

Morpht: Announcing Webform Mass Email port for Drupal 8

Planet Drupal - 9 November 2017 - 1:57am

The Webform Mass Email module has now been ported to Drupal 8. Time to get emailing :)

The Webform module has long been a powerhouse for Drupal site builders, providing a flexible solution to one of the central problems of web development: collecting user data, storing it and notifying users when content is added. the Webform module has been extended in many directions, supporting ancillary workflows and use cases.

One such use case is sending a mass email to all subscribers to a Webform. This can be handy for when users are signing up to an event or have registered their interest in a topic. The Webform Mass Email module fills this gap.

The module works as follows

When installed, Webform Mass Email module adds a new sub-tab called "Mass Email" under all Webform's "Results" tab (next to "Submissions", "Download" and "Clear") and one settings sub-tab called "Mass Emails" under global Webform "Configuration" tab (next to "Exporters", "Libraries" and "Advanced").

  1. Site builder navigates to the "Mass Emails" tab and set base module settings once.
    • "Cron time" - How much time is being spent per cron run (in seconds).
    • "Allow sending as HTML" - If checked, all emails are processed as HTML formatted.
    • "Log emails" - Should the emails be logged to the system log at admin/reports/dblog?
  2. The site builder can then assign "Send Webform Mass Email" permission for roles which are able to send mass emails.
  3. Anyone with this permission can then navigate to the "Mass Email" sub-tab of any Webform and send messages.
    • "Email field" - The field that is going to be used as the recipient's email address.
    • "Subject" - Message subject for your email.
    • "Body" - Message text for your email.
  4. After you hit the "Send emails" button, messages are inserted into queue and sent when cron is running.

The module has now been ported to Drupal 8 and is being supported by the team at Morpht. Check it out and let us know what you think.

Categories: Drupal

Acquia Commerce Manager

New Drupal Modules - 9 November 2017 - 1:17am
Categories: Drupal

Ubercart Recently Viewed Products

New Drupal Modules - 9 November 2017 - 12:41am
  • Download the latest release of this module
  • Uncompress the archive in your modules contrib directory:
    [your Drupal root]/sites/all/modules/contrib/
  • Enable the Ubercart Recently Viewed Products module under 'Ubercart - extra' in the Drupal module administration page.
  • Module configuration can be done from : admin/store/settings/recently-viewed-products
  • Go to admin/structure/block
  • Assign Ubercart Recently Viewed Products block to theme region
Categories: Drupal

Behind the Counter: The Customer is Not Always Right

RPGNet - 9 November 2017 - 12:00am
The return of Behind the Counter.
Categories: Game Theory & Design

Dropsolid: James & Jenny, our toolbox for faster Drupal development

Planet Drupal - 8 November 2017 - 11:30pm
09 Nov James & Jenny, our toolbox for faster Drupal development Nick Vanpraet Tech Drupal 8

Be aware, this is a longread with extensive value. Only read this if you are ready to uncover our Dropsolid team's exciting dev tool and platform secrets!


James & Jenny might sound more like a comedy double act or the protagonists of an long-forgotten tale, but they are in fact very much alive and kicking. They are the names we gave to the platforms that we developed in-house to spin up environments faster and get work done more efficiently. How? Read on!


In practice

Whenever we want to spin up a new server, start a new project or even create a new testing environment, we still rely on our infrastructure team. A while ago we managed to automate our build pipeline with some smart configuration of Jenkins, an open source piece of software. Combined with a permission system, we are already able to let technical clients or consultants participate in the development process of a site by triggering a build of an environment. We decided to call this home-coded piece of software James, our in-house Drupal Cloud Butler. However, this UI was very cluttered and it was easy to break the chain. Maintenance-wise, it wasn’t the friendliest system either. James 0.1 was very helpful, but needed polishing.

Behind the scenes we started building a proper platform that was designed to supersede this existing system and take over the creation of new servers, projects and environments by adding a layer on top of this - a layer that could talk to Jenkins and would be able to execute Ansible playbooks through a managed system via RabbitMQ. You could see this as James 0.2. This version of James only has one account and isn’t built with a great many permissions in mind. Its purpose is very simple: get stuff done. This means we still can’t let clients or internal staff create new environments on James directly or set up new projects. But we’d really like to.

This is why we’re currently also investing heavily in the further development of Jenny, the site-spinning machine. Jenny’s aim is to be a user-friendly layer on top of James and it consists of of two parts: a loosely decoupled Angular application consuming a Drupal 8 backend exposed through a REST API, which in turn talks to James through its REST API. Because Jenny makes sure only calls that are allowed go through to James, James can stay focused on functionality without having to add a ton of logic to make sure the request is valid. If the person who wants that new environment isn’t allowed to request one, Jenny won’t ask James to set it up in the first place.


How it works


A Jenny user will be able to create a new organization, and within that organization create new projects or clone existing ones. These projects can be housed on our servers or on external hosting (with or without VPN, Firewalls or anything else that’s required). They’ll be able to create new environments, archive entire projects or just a single environment, build, back up, restore, sync across environments, log in to an environment’s site, etc. It will even contain information about the health of the servers and also provide analytics about the sites themselves.

Now, because single-person organisations are rather non-existent, that user will be able to add other users to their organization and give them different permissions based on their actual role within the company. A marketeer doesn’t need to know the health of a feature-testing environment, and a developer has little use in seeing analytics about the live environment.

The goal of this permission system is to provide the client enough options that they can restrict a developer from archiving live but allow them to create a new testing environment and get all needed information and access for that environment. On a sidenote: these aren’t standard Drupal permissions, because those are for members within an organization, and a single user can be a part of many organizations and have different permissions for each one.



But all these layers have to be able to talk to each other before any of that can happen. JennyA(ngular) has to talk to JennyB(ackend), JennyB then has to make sure the request is valid and talk to James. And whatever information James returns, has to be checked by JennyB, stored in the database if needed, and then transformed into a message that JennyA can do something with.

To make sure we can actually pull this off, we created the following test case:

How do we trigger a build of an environment in Jenkins from JennyA, and how do we show the build log from Jenkins in JennyA?

JennyA: build the page, get project and environment info from JennyB, create a button and send request to API. How this process happens exactly, will be explained in a different post.


For this REST resource we need two entities: Project and Environment.
We create some new permissions (defined as options in an OrgRole entity) for our Environment entity type:

  • Create environment
  • Edit environment
  • Delete environment
  • Archive environment
  • View environment
  • View archived environment
  • Build environment

Next to this, we build a custom EntityAccessControlHandler that checks these custom permissions. An AccessControlHandler must have two methods: checkAccess() and checkCreateAccess(). In both we want to make sure Drupal’s normal permissions (which for this entity we reduce to simply ‘manage project environment entities’) still rule supreme, so superadmins can debug everything. Which is why both access checks start with a normal, bog-standard $account->hasPermission() check.

if ($account->hasPermission('administer project environment entities')) { return AccessResult::allowed(); }

But then we have to add some extra logic to make sure the user is allowed to do whatever it is they’re attempting to do. For that we grab that user’s currently active Membership. A Membership is a simple entity that combines a user, an organization, and an OrgRole entity which says what permissions the user has within that organization. For non-Create access we first check if this user is even a part of the same organization as the entity they’re trying to save.

// Get the organization for this project environment $organization = $entity->getProject()->getOrganization(); // Check that the active membership and the attached organization match $accessResult = Membership::checkIfAccountIsPartOfCorrectOrganization($organization, $account); if ($accessResult->isForbidden()) { return $accessResult; }

For brevity’s sake, I won’t explain how exactly checkIfAccountIsPartOfCorrectOrganization does its checks. But it returns an AccessResultInterface object and does exactly what it says on the tin. It also includes a reason for forbidding access, so we can more easily debug problems. You can just add a string to the creation of an AccessResult or use $accessResult->setReason() and you can then grab it using $accessResult->getReason(). Take note: only forbidden and neutral implement that method. Make sure the result implements the AccessResultReasonInterface before calling either method.

if ($accessResult instanceof AccessResultReasonInterface) { $accessResult->getReason(); }

We use this extensively with our unit testing, so we know exactly why something fails.
Assuming our test passes, we can finally check if this user has the correct permissions.

$entityOrganizationMembership = User::load($account->id())->getActiveMembership(); switch ($operation) { case 'view': if (!$entity->isActive()) { return $this->allowedIf($entityOrganizationMembership->hasPermission('view archived project environment'), 'member does not have "view archived project environment" permission'); } return $this->allowedIf($entityOrganizationMembership->hasPermission('view project environment'), 'member does not have "view project environment" permission'); case 'update': case 'delete': case 'archive': case 'build': return $this->allowedIf($entityOrganizationMembership->hasPermission($operation . ' project environment'), 'member does not have "' . $operation . ' project environment" permission'); } // Unknown operation, no opinion. return AccessResult::neutral('No operation matches found for operation: ' . $operation);

As you might have noticed, normally when you load a User you don’t get a getActiveMembership() method. But we extended the base Drupal User class and added it there. We also set that new class as the default class for the User entity, which is actually very easy:

function hook_entity_type_build(&$entity_types) { if (isset($entity_types['user'])) { $entity_types['user']->setClass('Drupal\my_module\Entity\User); } }

Now loading a user returns an instance of our own class.

For createAccess() things get trickier, because at that point the entity doesn’t exist yet.This makes it impossible to check if it’s part of the correct organization (or in this case, the correct project, which is in turn part of an organization). So here we’ll have to also implement a field level Constraint on the related project field. This article explains how to create a field level Constraint.

In this Constraint we can do our Membership::checkIfAccountIsPartOfCorrectOrganization check and be sure nobody will be able to save an environment to a project for an organization they are not a part of, regardless if they are creating one or saving one (somehow having bypassed our access check). To make doubly sure, we also set the $validationRequired property on our Environment class to true. This way entities will always demand to be validated first. If they are not, or they have errors, an exception will be thrown.

Now we can finally build our rest resource. Since a Jenkins build doesn’t exist as a custom entity within JennyB (yet), we create a custom REST resource. We use Drupal console for this and set the canonical path to “/api/project_environment/{project_environment}/build/{id}” and the “create” path to “/api/project_environment/{project_environment}/build”. We then create another resource and set that one’s canonical to “/api/project_environment/{project_environment}/build”, the same as our first resource’s “create” path. This way, when you POST to that path you trigger a new build and when you GET you receive a list of all builds for that environment. We have to split this off into two resources, because each resource can only use each method once.

We generate these resources using Drupal console. But before we can begin with our logic proper, we have to make sure the ProjectEnvironment entity gets automatically loaded. For this we need to extend the routes method from the parent class.

public function routes() { $collection = parent::routes(); // add our paramconverter to all routes in the collection // if we could only add options to a few routes, we would have // to loop over $collection->all() and add them to specific ones. // Internally, that is exactly what the addOptions method does anyway $options['parameters']['project_environment'] = [ 'type' => 'entity:project_environment', 'converter' => 'paramconverter.entity' ]; $collection->addOptions($options); return $collection; }

In the routes method you can add or remove options and requirements to your heart’s content. Whatever you can normally do in a routes.yml file, you can also do here. We've explained this in more detail in this blog post.

Let’s take a closer look at our create path. First we’ll need to make sure the user is allowed to build. Luckily thanks to our custom access handler this is very easy.

// check if user can build $entity_access = $projectEnvironment->access('build', NULL, TRUE); if (!$entity_access->isAllowed()) { // if it’s not allowed, we know it’s a forbidden or neutral response which implements the Reason interface. throw new AccessDeniedHttpException($entity_access->getReason()); }

Now we can ask James to trigger the build.

// Talk to James $data['key'] = self::VALIDATION_KEY; $url = self::API_URL . '/project/' . $projectEnvironment->getProject() ->getRemoteProjectID() . '/environment/' . $projectEnvironment->getRemoteEnvironmentID() . '/build'; $response = $this->httpClient->request('POST', $url, array('json' => $data)); $responseData = json_decode($response->getBody()->getContents(), TRUE);

For this test we use a simple key that James uses for authentication and build the URL in our REST resource. Eventually this part will be moved to a library and the code might look something like this:

$remoteProjectID = $projectEnvironment->getProject()->getRemoteProjectID(); $remoteEnvironmentID = $projectEnvironment->getRemoteEnvironmentID(); $response = $this->jamesConnection->triggerNewBuild($remoteProjectID, $remoteEnvironmentID, $data); $responseData = json_decode($response->getBody()->getContents(), TRUE);

We check the data we get back and if everything has gone well, we can update our local ProjectEnvironment entity with the new currently deployed branch.

if ($response->getStatusCode() == 200 && $data['key'] !== $projectEnvironment->getCurrentlyDeployedBranch()) { // Everything went fine, so also update the $projectEnvironment to reflect what // the currently deployed branch is $projectEnvironment->setCurrentlyDeployedBranch($data['branch']); // validate the entity $violations = $projectEnvironment->validate(); foreach ($violations as $violation) { $errors[] = $violation->getMessage(); } if (isset($errors)) { throw new BadRequestHttpException("Entity save validation errors: " . implode("\n", $errors)); } // save it $projectEnvironment->save(); }

Running validate is necessary, because we set the $validationRequired property to TRUE for our entity type. If something goes wrong, including our custom Constraints, we throw a Bad Request exception and output the validation errors.

Then we simply return what James gave us.

return new ResourceResponse($responseData, $response->getStatusCode());

On James’ end, it’s mostly the same but instead of checking custom access handlers, we (for now) just validate the key. And James in turn calls Jenkins’ API. This will also change, and James will hand off the build trigger to RabbitMQ. But for the purpose of this test, we communicate with Jenkins directly.

James then returns the ID of the newly triggered build to JennyB, who returns it to JennyA. JennyA then uses that ID to call JennyB’s canonical Build route with the given ID until success or failure has occurred.


Curious to read more interesting Drupal-related tidbits? Check out the rest of our blog. Or simply stay up to date every three months and subscribe to our newsletter!

Categories: Drupal Using lots of different tools? Do it all in Drupal instead!

Planet Drupal - 8 November 2017 - 9:43pm

You need a website. You need to send an e-mail newsletter. You need to track (potential) volunteers, donors, or customers. You could use Drupal, Mailchimp and HubSpot. Or you could do it all in Drupal.

We've been using the tools above in our own organization, and we continue to use them. Yet, we've been toying with the idea of moving more of our daily usage to a more Drupal based solution. I'll try to outline some of the pros and cons of each approach. I think you'll see for many organizations the Drupal solution could end-up on the winning side of the decision!

The Heavyweight Single Purpose Tools

We've used a number of we based services at myDropWizard to help keep sales, projects, and customer communication on track.

I'll outline just a few that we use that are very popular. that would make for a good comparison with a Drupal solution.


Currently, we use MailChimp for newsletters. I think MailChimp is a champion product with low prices and great features. MailChimp is probably the most used email newsletter platform, so it's strengths are well known.

Categories: Drupal


Subscribe to As If Productions aggregator