How to Add C# Assemblies to a Godot Engine Project

With the release of version 3.0 of the Godot Engine, C# was added as a supported programming language. Due to other engines like Unity, there is a large number of C# assemblies which can help in developing a game. However, there isn’t an easy way to add assemblies in the editor. Therefore, this tutorial was created to help with that problem.

In this tutorial, we’ll use the Godot Engine, version 3.0, along with the assembly for Rant. Note that while a C# assembly can be added to the editor, the assembly cannot be exported to a self-contained executable just yet.

1. Create project as normal. Where necessary, add a C# script. At first, the engine will generate the necessary C# files (i.e. the “*.csproj” and “*.sln” files).

2. Add in the C# code. After this, close the editor for the moment.

3. Ensure that the correct assembly is in the Godot project working directory.

4. Go into a desirable IDE and open up the “*.csproj” file which was created when the C# script was added. Monodevelop will be used in this tutorial. At this point, ensure that the Godot editor isn’t running. Otherwise, key files may be overwritten.

5. In Monodevelop, right-click on the References node in the tree view for the project and click on Edit References... Be sure to first expand the project so as to reveal References. Then click on the .NET assembly tab and click “Browse…”.

6. Select the desired assembly for the project and then click “Open”.

7. It should then be added as a reference for the project. Click “OK” and save the project (“Ctrl + S” or “File -> Save”). Exit out of the IDE and go back into the Godot editor.

8. Add in a GDscript which makes use of the assembly.

9. If all goes well, the engine should use the assembly in the resulting game.

If you have any comments or questions, please ask them below, or get in touch with me.

Connecting your JLab Intro headphones on Elementary OS

The JLab Intro headphones are a low-cost pair of Bluetooth headphones. Though not the best, the sound is still decent. Here’s how to connect the headphones on Elementary OS.

First, put the headphones in discovery mode. To do this, press and hold the on/off button for about six or seven seconds, until it starts flashing red and blue.

Then use Bluetooth Manager (use apt install blueman to install it) to search and select the headphones (they’ll show up as “JLab Neon BT”):

Once you select it, click on “Create a pairing with device” (click the “lock” icon), and Bluetooh Manager will attempt to pair with the headphones.

Right-click on the device and select “Headset”. This should tell the headphones to act like an audio device.

Go into “System Settings” -> “Sound” and select “JLab Neon BT”. Click on the “Mode” dropdown menu and select “High Fidelity Playback (A2DP Sink)”. Some sort of sound should be playing through the headphones. You can also adjust the volume through the volume control on the headphones.

After that, you can use the “Test Sound” utility to test that the sound is working.

Auditing a charity’s network, and finding something out of place

For the past six months or so, I have been helping a local charity with its I.T. needs. This includes updating their computers, designing and setting up a kiosk for its volunteers, and helping other charity members with their IT needs. Now I’m trying to map their network, and help the director of I.T. to ensure that all devices (desktop computers, printers, external hard drives, etc.) are accounted for.

About two or three weeks ago, I used nmap to do a quick scan of the local network, and check the devices on the network for what they were broadcasting, what ports were open, and just what that exact machine is. After finishing that, I met with their director of I.T. to discuss my findings. He verified most of what I found (we had a problem with one of those Western Digital MyCloud hard drives, but that was soon cleared up). But there was one part which baffled the both of us.

Just like many other small organizations, they use old phones. The ones they use are Avaya IP phones (i.e. voice over internet protocol [VoIP] phones), model 1616. I don’t know when they got these phones, but they’re old. When I scanned these phones, I only got their IP addresses; there was no hostname. However, on one particular phone, I found a hostname. It’s not a hostname you would find on any of the other computers on the network (they had hostnames that ended in “.local”). This one had the hostname “”. How it got this hostname, I am not entirely certain.

At first, I thought these were phones with a few features (voice mail, call fowarding, conference calls, stuff like that). As I have found out, these phones are fully featured, and have upgradeable firmware. The phone in question, the model 1616-1 BLK, gets its firmware from the local Avaya phone PBX server. Since it gets its firmware from the server, how can the hostname be changed? In the settings for the phone, the hostname can’t even be changed. One of the members of the charity’s administration said that they had problems months ago with the voice mail system. But I doubt that’s related to this problem.

So how should I approach this? Has it been hacked? Is it just a software glitch? Hopefully it’s nothing serious. The I.T. director said that he bought a bunch of these old phones on the cheap years ago, and he’ll look into flashing the firmware on the phone. So let’s hope that’s the last we’ll hear of it.

Using Rant in my Python program because I’m a glutton for punishment

Over the past few months, I have been researching and developing a little procedurally generated game which will eventually be created in the Godot engine. This game will have a story that’s procedurally generated for the players. A part of this game is the dialogue, which will also be procedurally generated. To accomplish this, I set out to find a library of some kind which can create procedurally generated dialogue (or at least the dialogue that I want) and is written in my programming language of choice, Python. From the looks of it, there isn’t one, and so I had to look elsewhere. That’s when I stumbled upon something called Rant. This is billed as a library which can procedurally generate dialogue. At first I thought I had found what I was searching for. Sadly, though, it is written in  the least open source-friendly language I have ever seen: C#. This can be used on Linux (with the Mono runtime). But I’m looking for a solution where I don’t have to use a bunch of programming languages to achieve what I want.

At first, I tried making some kind of dialogue scheme that would suit my needs. I threw in some sentences of what may define the NPC, and mashed it all together. From the looks of it, though, the scheme is getting out of hand. I have several lines of dialogue, and I’m not even finished. I don’t entirely know how I’ll fit it all together, considering this is just for a simple demo of the full game. It looks like I’m going to have to get creative.

I went digging and searching around I came upon several possible ways of integrating C# code into Python code. There’s IronPython, a fully implemented version of Python in C#. The big problem with this was that it didn’t look very portable to me, as I would have to bundle the .NET libraries with the game for each platform, and that’s a royal pain the ass. Then I looked at Python.NET, which looked very promising: you can call some C# code from Python, and you can call some Python code from C#. It looked like the best of both worlds. Now, actually making it work is a bigger problem.

When I tried to use the Rant.dll assembly in my Python program, I found that I can’t do that because, well, it’s C# code, and the regular old CPython (which comes with many Linux distributions) can only import C or C++ code. Then I looked into using the clr module from Python.NET, but I couldn’t find a version built for Linux. Through a lot of hand wringing, brow beating, and code cracking, I found that I had to use the latest version of Mono (version 5.0.1) along with an unstable version of Python.NET. This one built with the suggested command: python build_ext --inplace. The built shared object library file, “”, and the “clr” module load in Python.  Heck, I was even able to load the pre-built “Rant.dll”. But this is nothing compared what I must do now: actually making some procedurally generated dialogue with Rant. And I don’t know where to begin with that.

So I Did a Panel at a Convention

Last Friday, I did a panel at A-Kon 28 about starting out with Gimp. I had been wanting to do a panel for a while, so I prepared for this one. I followed the advice of the dynamic duo that is Vitamin H, and planned out what I was going to say, along with practice. While I did write out an outline, along with the practice, that didn’t really prepare me for the panel.

I practiced the panel at a local community college. While that served to focus what needed improving, I couldn’t get proper feedback on what was missing from the panel. I don’t know any artists, and friends of mine couldn’t take time off to come see it. Even when I recorded the practices, I couldn’t get people to look at it, nor critique it. So I had to just think of how the audience would react to it. I did this each Friday, for a few weeks, up until the convention.

Before I started the panel, I was nervous. I thought of how to properly show the panel, including the video set-up. I also looked at how few people were in line, so I thought that it would not be a big crowd. Then, when they allowed people in, the room quickly filled. At that point, I knew I was screwed.

I led off by introducing myself, talking about the program, and possibly where you can get it. Then I showed off some of my pictures. I showed one I made for Kirby’s Epic Yarn, along with a parody of a movie poster. When they laughed at the joke, I thought, “Nailed it.” But then it went downhill from there.

I kept trying to show the audience some of the finer details of Gimp, but I couldn’t exactly talk about the tools. The settings for the paintbrush tool were pretty self explanatory, so maybe I shouldn’t have gone in that direction. Also, the picture that I used for an example didn’t really seem to work for the audience. I had already inked it out, so I couldn’t show the full capabilities of the ink tool. I did talk about the “dynamics” feature, and I think they got that. But talking about how to use the bucket tool, and the selection tools just fell apart. Heck, I couldn’t even tell whether the audience was learning something.

Near the end of the panel, half the audience left. Those who did asked questions, and I was able to answer a few of them. One guy asked about the blending capabilities of Gimp, and so I tried to answer his question to the best of my abilities. I couldn’t understand whether he was talking about the blend modes of the layers, or the blending capabilities of the brush tool. Still, he kept his interest. Other people asked about the settings, but I couldn’t really answer that. From the looks of it, only a handful of the audience learned something.

The next time I do this, I’ll have to get people to give me feedback on what I’m planning. Also, I’ll have to define exactly for whom this panel is targeted.

How About Those Hidden Costs?

Usually, when a business owner draws up their budget, or when they’re forecasting, they try to get all of the information necessary to make a decision. So they check as many costs as they can, see which ones they can control, see how they can turn a profit, and move in the right direction. Sadly, not all business directors (or, really, many people who try to look at their costs) can find all of the costs. At times, it could be that they can’t see how some costs affect their business.  Or, they don’t see the costs at all. The reason could be that they can’t look at the costs at different levels.

Let’s take the cost of food.  Many will say that the cost of food has increased. I have heard that it’s less expensive to eat out than it is to buy your own ingredients. But this is not always the case. A person can buy the ingredients and choose the size of portions which go into the meal. Unlike a restaurant, where their portion sizes tend to be fixed (or even decrease after about a year), a home cook can just throw in a few units of the ingredient, and have a meal. Heck, when I’m cooking something and using a recipe, I always slash the units that the recipe uses, and go with half the amount. I can save the ingredients for another day, or even make leftovers. But saving on the size of the ingredients and food is only a part of looking at it.

In a recent article on the BBC, it was said that an American woman in the 50s and 60s would spend hours in the kitchen preparing meals. Not all of these women were average; some were highly educated and came from well-to-do families. Food preparation in the home was the usual thing to do. But in the 60s, prepared foods, like TV dinners, came on to the scene. More and more the mother would spend less time in the kitchen. So is this a good thing? Again, it depends on your perspective.

Now that people don’t need to spend so much time in the kitchen, they are freed up to do other things. Things such as eating out, which is what many people do. The BBC article says that Americans spend more on food and drink outside of the home than inside the home. So when a family looks at their grocery bill and gasps at how high it is, they usually don’t contrast this with how expensive eating out can be. The food that the restaurant makes is usually great, but that comes at a high cost, too. The cost to acquire that food usually varies, but it may be a lower cost than the cost of buying it at grocery store (often times, it is). The restaurant, though, has to add in the cost of many other things, such as labor and rent, because they need to turn a profit.

How does this relate to other businesses? The metrics the business may use to determine how costly something is may only be one way of seeing it.  For instance, a company may look at how much power their servers use, which is usually measured in watts per hour. This metric can be used to determine whether to buy servers, or to outsource it (maybe for cloud services). While this is a perfectly good metric, one other metric to consider is how many times the proposed company has had outages at their datacenter, and how they’ve handled these outages.  One other metric (albeit a more involved one) is the cost of moving the company data once the contract has ended with the outsourced company. These are just some examples of how a company should look at possible costs differently.

Please note that I’m not saying that the decision-makers at companies don’t take as many costs into consideration. Ideally, they will take all of the important costs into consideration. The problem is looking at what costs really matter, and what the company can do about them.

Trying My Hand at Making a System for Procedurally Generating Stories

Last year, I got the idea of making a game where a group of friends could get together, have a game scenario generated for them, and they could start playing.  This is something called procedural generation, wherein game settings, mechanics, assets, and other components are created from an alogorthim, and a bit of randomness.  I thought I would just research this, since creating any sort of video game takes a lot of time and skill.  In this case, I was looking into a system for creating stories.

I’ve read a few things about procedurally generating stories (for instance, Tail-Spin and Minstrel) and I stumbled upon one that may be in my reach.  From a paper titled “Random Word Retrieval for Automatic Story Generation” I found out about something called ConceptNet.  This is a commonsense knowledge database for finding the relations between concepts via semantics.  So you can find one concept (like “dog”) and find corresponding concepts for it (such as “animal”).  The paper talks about the intent of making a system for using ConceptNet to find the relations between words (in a process called “Concept Correlation”) and make a story out of it.  Sadly, they haven’t yet implemented the system.  So what I’m trying to do is make something that will, uh, sort of make a story.

In the paper, they talk about how the system requires a Knowledge-Based System.  Unfortunately, this system is quite tedious and difficult to create (or so the paper says).  So I’m just trying to find the connections between words and concepts.  All that I’ve been able to do, though, is mess with the Python interface to the ConceptNet website, and maybe find some related terms.  Finding the connection between two dis-similar terms is difficult, because the concepts have many branching nodes which connect to other nodes.  Finding the right nodes which connect the two concepts would take a while, because the system would have to iterate over the nodes until they find a match.

The examples I’ve been using have been “dog” and “snow”.  So the system would have to go through each node in the “dog” concept until it found a node which connects to “snow”.  It could be any connection from “dog” -> hasA-> “nose”  -> RelatedTo-> “wet” -> PropertyOf -> “snow”.  Please note that these aren’t actual connections in ConceptNet, but something like this can be found in the database.

So I don’t know how I’m going to tackle this monster, let alone make a story out of it.

Newer Ways of Audit Reporting on Third Party Companies

I went to a recent meeting of the North Texas chapter of ISACA, and there was a presentation on SSAE 18.  For those of you who don’t know, SSAE 18 supersedes SSAE 16, and consolidates Service Organization Controls reporting into something more manageable.  Here, I’ll talk about what I’ve learned about SSAE 18, SOC 1, and SOC 2.

In SSAE 18, more emphasis has been put on testing the design of controls for subservice organizations (e.g. third parties for which the organization has contracted out some process) and whether they are doing what they are suppose to be doing.  The auditor, through Service Organization Control (SOC), has to report on the effective use of these controls.  In the case of a SOC 1 report, they would assist in testing the controls as they pertain to the financial statements.  With SOC 2, the auditor reports on the controls with regards to security, availability, integrity, and confidentiality.

Now the auditor has to look for things such as complementary user entity controls, which are the controls that are assumed to be in place for users.  The auditor will have to look at reports from the subservice company to the main organzation.  They will have to see whether the organization is actually verifying the information in the report.  For instance, the auditor will have to see system-generated reports are being validated by the users of these reports.  The processing integrity principle will be used heavily in this situation.

This audit will look at how management has chosen the suitable criteria for the control, and how well they’ve measured the subject matter (note that “subject matter” means the risk relevant to entities using the subservice company).  So an auditor will look at whether the risk is something related to the entity’s business with the subservice company, then check the metrics of the current control, and see whether they are actually related to the control.

Migrating My Nextcloud Server to Another Server

When I saw that my version of Ubuntu could not be upgraded any more (due to Digital Ocean’s system), I had to migrate my Nextcloud installation (version 11.0.2) to a newer version of Ubuntu (16.04). In the documentation for Nextcloud, it details how to exactly migrate your Nextcloud installation to another Linux server, so I tried using that. Sadly, though, they left a couple of things out. So here’s my version of how I migrated my Nextcloud installation to another server.

First of all, they say to back up your data, which is what I did (to some extent). Next, I spun up a droplet which had similar specifications to my previous installation (it uses 512MB and has 20GB of storage, for instance). I made sure to put in my usual ssh key for this new droplet, as well as securing it in other ways. At first, I thought I knew how to easily do this: copy over the /var/www/nextcloud directory to the new server (which was also set up for Nextcloud), change some directory names, and it would be done. However, this was not what I found.

When I tried this method, I couldn’t access the web interface. What was worse was that I had forgotten to change the firewall configuration on the new droplet and accidently “locked” myself out. So, through some more research, I tried it again with another droplet.

This time, I copied the files using rsync, and made sure that I used the proper switches (I used the “-a” and “-t” switches, in order to archive the files, as well as save the timestamps). I saved the files to a new directory on the server, and made sure to back up the old files. I thought that this time I had fixed the issue. But Fate can be cruel.

Even though I had copied over the files in the “correct” fashion, the server still wasn’t accessible from the web. Looking at the /var/log/apache2/error.log file, I found that the webserver couldn’t start due to Nextcloud not be able to read the database. After researching the problem more, I learned that the data can’t be just “copied” over; rather the data has to be copied, and the database has to be imported. So, after scrapping that droplet (I had changed it too much already), I spun up a new droplet, and tried this whole thing all over again.

First, I put the server into “maintenance mode” and stopped the Apache server. Then I extracted the data from the database (via the command mysql -u ownCloud -p password ownCloud > /tmp/dump.sql), copied that over to the new server, and imported it into the new database. For importing the new database, I “dropped” the old database, created a new one, and finally imported the data with the command mysql -u nextcloud -p password nextcloud < /tmp/dump/sql. Then I copied the old Nextcloud as I did before (using the official documentation’s recommendation of the command rsync -Aax) and carefully moved the files into the new /var/www/Nextcloud directory. Even through all of this, it still wasn’t enough.

Looking again at the /var/log/apache2/error.log file, I found that the new Nextcloud install couldn’t read the database due to the new server using the old Nextcloud config.php file (are you still with me?). So, I changed a few values in the config.php file so as to use the new database. What I did was change the dbname to the name of the new database, as well as input the new database login information. Also, I added the new IP address to the “trusted hosts” array in the config.php file. This seems to have fixed most of my problems.

Just in case, I also ran a script that I found in the official Nextcloud documentation for fixing the permissions on the new server. Then I changed some of the security configurations for the Apache server. I copied over previous configurations for SSL into the /etc/apache2/sites-available directory, and enabled them through the a2enmode command. With all that finished, I started up the Apache server again, and took the Nextcloud installation out of “maintenance mode”. Finally, I was able to use the server. Except, it wasn’t exactly to my liking.

You see, I had copied over the “data”, “config”, and “themes” directories. I did not copy over all of my previous apps. When I saw that I had only half of my previous apps, I thought, “I need to fix this,” and copied the contents of my previous Nextcloud’s “apps” directory to the new server. With those out of the way, I saw to using some of Nextcloud’s recommendations, and bumped up the memory (as well as putting in a timeout feature). These were harder to fix, partially because I had these problems with my previous Nextcloud installation. Nevertheless, I sought to fix them.

One of my problems was with the /var/www/nextcloud/.htaccess file, specifically that it wasn’t working. To fix this, I edited the /etc/apache2/apache.conf file and changed the AllowOverride directive for the /var/www section to “All”. This allowed the /var/www/nextcloud/.htaccess to work (at least, it would work since I’m accessing the site over a secure connection). Next, I added a memcache so as to speed up performance. I added in php-apcu and edited the /var/www/nextcloud/config/config.php file to reflect this by assigning memcache.local the value \\OC\Memcache\\APCu. My server was made much faster with this tweak. For added polish, I followed the directions on this tutorial and added Redis support.

This was a tough migration that I thought would have been easy. I figured that it would have taken a couple hours. However, it was stretched out to a numbers of hours (not to mention one night). While it’s great that I have migrated to a more manageable configuration, I should have done more research.

Helping Out a Local Charity

I’ve been helping out a local charity with preparing tax returns for the needy and underprivileged for the past few weeks and we’ve run into a problem. Each time we have to print out the tax returns for the clients, we have to take the laptop over to the printer to have it printed out.  This takes a while, and it can be a royal pain.  So I have suggested setting up a small print server so that the laptops on the WLAN can easily print.  My initial set-up looks encouraging: I have set up a Raspberry Pi as a little print server, and have successfully printed from one of the laptops.  With some security measures and other set-up, the other laptops that the tax preparers are using will be able to use this print server, too.