Using Java Sockets to Communicate Between Servers in a Network

I recently got hired to re-write a large game in Minecraft, similar to classic Survival Games. It needs to run on a network, allowing for multiple game servers to go on as well as multiple servers to connect from.

The servers the players can connect from needed to know the game status, map, mode (there were different types/remixes of gameplay), entry fee (cost to join), current player count, and maximum player count. All these would be displayed to players when viewing the ongoing games, and would also be used to partially judge whether or not a game would be open to players.

Minus a few features, the previous installation of the game used a MySQL database to store information about the server. I felt that MySQL was the wrong way to go about storing what should be stored in memory, and instead, I went the route of using a central server from which both game servers and join-from servers could contact for data, similar to Minecraft packets.

The game network consisted of the game plugin/server, a plugin on the BungeeCord proxy network, and another for the join-from server.The game server would send data in the form of a JSON string to the Bungee socket server, which would then forward it to the join-from servers. When a player wanted to join a game, the join-from server would send a packet to the game server (forwarded from Bungee) in order to double check that the data is consistent. If it all checked out, the Bungee server would send the player from their current server (storing it so they can be moved back later) to the game server, where the game server would handle every new player joining.

Using DialogFlow Intent Detection to Get Data from a Minecraft network

I spend quite a lot of time on the Spigot developers forums, and one thread caught my attention. Coincidentally, I'm working on the same project the thread author started months ago (under a network). He was looking for some help with getting a service called DialogFlow to integrate with his Minecraft network.

DialogFlow is a service by Google which integrates with things like Google Home and Amazon Alexa to allow users to ask questions and for custom services to handle the response. The way it works is the developer creates an "intent", an action/question that a user can ask. They can then add parameters to the intent which are automatically parsed from the question and sent over to your handling server. In this case, the author wanted to allow users to ask "how many players are on server <x>?". The intent could be called "PlayerCount", and the parameter would be the server (<x>). After giving it a few training phrases (and selecting the parameter from those phrases), it gets really good at recognizing which word is the correct parameter.

Once it's parsed the question correctly, it then sends a request to your webhook. A webhook is a URL that data can be sent to by a service, usually an update or notification, which is then handled by the service. DialogFlow sends the Intent name, parameter(s), the full phrase, and other data to your webhook server, which then checks the given server player count and sends back data with whatever response you want. 

This is the first time I've done HTTP backend in Java/Kotlin, so I used a library called Spark to simplify things (as opposed to using the builtin HTTP library).

Maven Plugin for Generating Spigot's plugin.yml in Spigot plugins

When creating plugins/projects for myself, I usually create libraries that can be re-used for different parts of the plugin. For example, I recently created an annotation powered command API in Kotlin. In addition to that, I've also created an input library using the trick I described earlier. It allows me to very easily listen for player keyup/keydown events as well as attach/remove the listener/mount entity for the player, without having to write out the messy packet code every time.

I'm also a big fan of unification in my projects - if I have to write something out twice, maintenance of that code becomes twice as hard. While this specific case isn't code, it does help to easily fill in details for my plugin. 

Bukkit (and subsequently Spigot) requires all plugins to contain a plugin.yml file in the root directory of the jar.  It contains information used by the server for logging and showing information to admins. There are three required fields, as well as many others which are optional. 

The first required field is the name of the plugin, usually in the format of UpperCamelCase (no spaces). It's used as the prefix for commands registered by the command (when a prefix has to be supplied), part of every message logged by your plugin, and generally allows administrators to find problem plugins from exceptions. The second required field is package path to the plugin main class, the class which is loaded by the server and contains a few utility functions. A typical main path might look like "com.scarabcoder.example.Example" where the last section is the class name itself. The final required field is the version of the plugin, which is usually paired with the plugin name during exceptions and helps when a consumer needs to report a plugin error.

With the possible exception of the main class, all those are readily available in the Maven build file (pom.xml), and should normally match exactly. There are also other optional fields in the plugin.yml, such as description or a list of authors, all of which can be taken from the Maven build file (<description>, <developers>, etc). 

After a bit of googling around, I found a basic intro to writing a Maven plugin in Java (though I adapted it to Kotlin). I had to look around a few open source plugins to find out how to get data from the Maven build file as well as add to the final compiled package, but after an hour or so I had it working. At the moment, it generates the following plugin.yml fields:

name: Taken from the <name> specified in pom, if none is found it's taken from the artifact ID
main: Can be overriden manually, otherwise it's set to <group>.<artifiact ID>.<name> (what I would recommend the path to be for a main class file). 
version: Taken from the <version> property in <properties>
description: Taken from the <description> tag
website: Taken from the <organization> tag
developers (list): Taken from all the developers listed in <developers>

Additionally, you can specify Spigot plugins your plugin relies on inside the <configuration> tag the Maven plugin, as well as plugins it should load before or soft depends on.
 

Annotation-based Hierarchical Plugin Command API

When a player sends a chat message from the client to the server beginning with a forward-slash ("/") the server treats it as a command and is processed accordingly. In vanilla Minecraft, an example might be "/tp ScarabCoder" where the command is "tp" and the first argument (arguments normally start after the command) is the player's name. As far as simple commands like that go, it's easy enough for the server to check for a player by the name of the second argument and if it exists simply teleport the command sender to the player it found.

Sometimes, though, commands aren't that simple. A good example of a much more advanced command is the /scoreboard command in vanilla Minecraft. It handles teams, certain elements on the HUD, and a few aspects around the player. The "root" command is /scoreboard, but it can be considered to have multiple commands with every section being a different command. For example, if you wanted to modify teams in any way you would run "/scoreboard teams <arguments>" (<> is commonly used to specify an argument name) would be the command to modify teams in some way. A more complete example:

/scoreboard teams add Test
/scoreboard teams remove Test
/scoreboard teams join Test

At that point, it's just as though the first argument ("teams") is just a specifying another section inside the scoreboard command. Unfortunately, the programming behind that is not treated as such. In reality, there are a ton of "if" statements checking for each possible argument, sometimes "sections" within sections. It can quickly build up and become a mess. This is a command ("/ticket" base) which I created for a plugin which allowed users to open support tickets. This command is only the moderator side, and contains the following usages:

/ticket close <id>
/ticket tp <id>
/ticket flag <id> <flag>
/ticket comment <id> <message>

The amount of code that I had to write, however, was insane. There were a ton of "if" checks to make sure the amount of arguments passed were in the correct amount, that tickets with a given ID existed, etc. Here's a screenshot of what it looked like, with a much smaller font size. It still doesn't show the entire command class, though.

LongCommands.png

About 80% of that are "if" statements or simply parsing statements to get a ticket object out of the ids given. This is stuff that must be done repeatedly, exactly something a computer should be doing instead of me. 

I've been working on a new large gamemode in which I try to use the best possible practices and create the cleanest code, at the cost of the time it takes to learn and write that code. One thing I was settled on was developing a better API for handling large commands and sections inside those commands.

This new API uses a hierarchy to manage sections, meaning a "teams" section would be inside the "scoreboard" section, in separate classes. Inside each section is a command, which requires arguments that are actually used as arguments and not used to go into another section. For example, the team command would be treated something like this:

scoreboard
    -> teams
        -> create(name)
        -> remove(name)

Where each command is treated something like a programming function. In fact, each command in my API is actually taken from a function, meaning not only is it easy to sort out where commands are it also acts exactly like a function would. For example, inside the TeamsSection class (where all commands inside the teams class is reachable via /scoreboard teams) there would be the create function:

CreateExample.PNG

You can specify pretty much whatever you want the command to have using the annotation's (optional) parameters. When a player executes "/scoreboard teams create test", the function is called with the first argument being the player's name and the second argument being "test" (the team name). Little to no manual processing has to be done, making it extremely easy to add commands. 

It also supports custom type conversion. This means that a parameter in the command function can be an Integer, and if it isn't a message is sent to the player and the function is never called. You don't have to convert the String to a Player as a username, you don't have to make sure that a string can be converted to an integer, it's all automated. You can also add your own converters, which in the ticket example I gave above would allow you to take a Ticket object as a parameter without having to check in every function that a string can be converted to an existing Ticket object. 

The final little feature is that it registers the command with Bukkit automatically, meaning you don't need to add any of the command's details in the plugin.yml. This is especially useful, since the API also allows you to specify aliases and descriptions and it's nice to have that all in one place. 

Getting WASD Movement Control Input From the Client

Brief Overview of Packets

All communication between the player (client) and the server is done via "packets". A packet is a collection of data, with the first entry defining what sort of packet it is. For example, when an entity is spawned in the world, the server sends a Spawn Entity packet to the client and the client will render that entity at the given location with the given fields. A server that operates according the specifications expected by the vanilla (unmodified) client is referred to as a "Notchian" server. It may be modified in any way, so long as the packets are sent and received in the same way as an unmodified server. This means that a server with Spigot plugins might not be considered vanilla (unmodified) but would still technically be a Notchian server. 

There's a public packet specification wiki updated by members of the community and by the Mojang team (unofficially) that contains an updated list of every type of packet and other useful information (inventory slot IDs, some NBT data documentation, etc), called Wiki.vg.

This means that everything a plugin can do is limited by what the client can understand. The server can send anything to the client that's supported as listed by the packet wiki, however. A mod, however, modifies the client and in most cases the server (to add support for whatever is modified in the client). If a new block is created, the modified server will send world data with that block, but unless the client already contains data in the form of a modification for that block (textures, models, etc) it will either ignore it or simply crash.

Getting Movement Controls

When the client moves the player, the updated location and velocity is sent to the server. The controls are handled by the client, and the position updating is actually done clientside. Of course, the server can send a packet back to cancel the position change on the client and simply not store the new position, but by default this isn't the case. That's why "hacks" are possible - they simply modify the client to send things such as staying in the air instead of following gravity (once again, done clientside) to the server. Anticheats will double check the data to make sure it's following (loosely) the same mechanics as a vanilla client. 

One feature which most plugin developers/server modifiers wish for on the client is the ability to get the exact WASD key presses. You could check if the player moves on a block in a certain block, but cancelling that move on the client will look strange as their viewpoint is shifted back to the starting point. 

One example where you may want to get just the movement controls without actually moving the player or doing your own movement calculations is a custom vehicle. In this case, we could say a helicopter. You can send entity packets to the client to create a sort of helicopter out of entity models by positioning them correctly, but controls will be tricky. You could send a flight mode enabled packet to the client and allow them to move in all six directions and simply move the entities along with the player, but unfortunately the delay between the client moving clientside and the entities' position being updated to the client will create an ugly delay (lagspikes, for example, could make the entities seem a little "jumpy").

There is another method of getting a player's movement controls. In vanilla Minecraft, there are vehicle entities such as the horse or minecart. When a player is mounted on a vehicle, movement controls are sent to the server to process and move the vehicle accordingly. This is because vehicles usually have different movement needs. A minecart, for example, must follow the tracks set down. It *can* be done clientside, but because of the many calculations needed it's much more efficient to simply take user input (that's important) and update the velocity of the vehicle from that. 

What's interesting, however, is that whenever the client is mounted on *any entity*, it sends these movement control packets to the server whether or not it means anything in vanilla Minecraft. Movement packets will be sent whether you're sitting on a horse or an armorstand (the client can be mounted on any entity, not just vehicles). The packet for this is listed on the technical wiki as "Steer Vehicle", and is also known as the "input" packet. It contains the following data:

Packets.png

The first two fields are the forward/backward and left/right fields. The last tells you if the action is the player jumping (pressing space, used by horses usually) or unmounting (player dismounting is handled serverside). From this packet, you can tell the WASD controls and get the space/shift keys aswell. 

To apply this to the helicopter example above, you can send spawn entity packet with an invisible armorstand, then another packet to mount the player on that entity. Once done, the client will send a movement packet every tick. From there you can listen for those packets either via ProtocolLib's API or injecting your own listener (I prefer injection, especially so that an external dependency isn't required). Get the forward/backward and left/right fields from the packet, and update the position of the helicopter entities and the mount entity, resulting in a synchronized client & entity movement feel. 

I first found this little trick from the Spigot forums. One user had used a custom map renderer to allow you to move a rendered screen on a wall using the WASD controls. I plan to use a combination of these features to move a 2D game screen in an upcoming game I've been working on.

MySQL: The Magically Perfect Data Storage Method for Performance

Let me walk you through a nightmare scenario that I experienced earlier this week when fixing some bugs on an older project from another developer. The project was fairly simple. It allowed players playing on the network to claim a location where they and their team members could quickly teleport back to at any time but could be destroyed by anyone else. It also included a moderator feature which allowed staff to see the history of a team's home locations, useful when they use it to get to otherwise unreachable areas (homes could be claimed anywhere a player could reach, even places they couldn't actually get to otherwise).

Here is how he had his MySQL database setup:

Team ID [PRIMARY] | Clan Data [TEXT]

Two columns. The first was the ID of the team from the 3rd-party teams plugin, the second was a nightmare of deserialized objects with character separators. Each home object had the following data:

  1. Clan name
  2. Location (x, y, z, and world name)
  3. The player who set it down (the ID of)
  4. The player who destroyed it, if destroyed
  5. The date it was set down (millisecond timestamp)

It was put into a serializable string, resembling something like this:

"5:3:7:world_146727_null_1517941648916"

And added to whatever was in the clan data column. After a few days, you would get something like this:

"5:3:7:world_146727_null_1517941648916|5:3:7:world_146727_null_1517941648916|5:3:7:world_146727_null_1517941648916|5:3:7:world_146727_null_1517941648916|5:3:7:world_146727_null_1517941648916"

Of course, because there was only one column, it meant that everything from the database was loaded into memory on server start. The project was fairly old (about a year and a half old), so there were 6,000 rows in the table, 90% of which were no longer used. On top of all that, the MySQL database wasn't part of the same machine as the server the plugin was running on.

Why would someone do all that? Couldn't they obviously see that it was horribly performance & resource intensive, that a flat-file storage method would have worked much better with the same method?

The truth is, people (new developers especially) see MySQL as somehow extremely quick at delivering data and being very performance friendly. The administrator - or whoever is installing/setting up the plugin - will see that it uses MySQL and automatically assume that it will work much better than using YAML or JSON flat-file. I don't doubt that this developer didn't know MySQL well, and may even have learned it on the spot just because the job description asked for some MySQL experience. 

That being said, here is how I would (and did) set up the MySQL table format:

ID (primary, unique, auto-incrementing) | clan ID | x | y | z | world | date (timestamp) | setter UUID | destroyer UUID (null if active)

The primary difference (which actually called for a rewrite of the entire project) is that each home has a separate row. This made it easy to just grab the active home, or grab just the homes created since a certain date (as was required by the staff history command). I could also very quickly write a statement to remove homes that were inactive and created before a certain date. For example:

DELETE FROM homes WHERE date < 1517941648916 AND destroyer != NULL

With the previous table format, this would have been impossible without downloading all the data in the database. 

(Tutorial) How to create cooldowns with Spigot

Before you start (prerequisites)

You don't need to have any extensive Java experience, but it helps to understand how some of the basic features work. The main point of this tutorial is to go over the method and it's implementation, not how Java features like Singletons work.
 

How we want it to work 

For these examples, we will use the command /cooldown as the feature. It can only be used once every 15 seconds.
 

(Pitfall) Method #1: Using Runnable Timer Tasks

Before we get into the most common and performance friendly cooldown system, I want to cover a commonly suggested method that you should avoid. It's suggested fairly often because of how simple it seems at first.

In this method, your plugin has a Singleton cooldown manager:

public class CooldownManager {

    private HashMap<UUID, Integer> cooldowns = new HashMap<>();

    public static final int DEFAULT_COOLDOWN = 15;

    public void setCooldown(UUID player, Integer time){
        if(time == null)
            cooldowns.remove(player);
        else
            cooldowns.put(player, time);
    }

    public int getCooldown(UUID player){
        return (cooldowns.get(player) == null ? 0 : cooldowns.get(player));
    }

    private CooldownManager(){}

    public static final CooldownManager INSTANCE = new CooldownManager();

}

It contains the basic methods for setting, getting, and removing from a cooldown map. Next we have the Command Executor:

public class CooldownCommand implements CommandExecutor {

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        //Player only command
        if(sender instanceof Player){
            Player p = (Player) sender;
            int timeLeft = CooldownManager.INSTANCE.getCooldown(p.getUniqueId());
            //If the cooldown has expired
            if(timeLeft == 0){
                //Use the feature
                p.sendMessage(ChatColor.GREEN + "Feature used!");
                //Start the countdown task
                CooldownManager.INSTANCE.setCooldown(p.getUniqueId(), CooldownManager.DEFAULT_COOLDOWN);
                new BukkitRunnable() {
                    @Override
                    public void run() {
                        int timeLeft = CooldownManager.INSTANCE.getCooldown(p.getUniqueId());
                        if(timeLeft == 0){
                            CooldownManager.INSTANCE.setCooldown(p.getUniqueId(), null);
                            this.cancel();
                            return;
                        }
                        CooldownManager.INSTANCE.setCooldown(p.getUniqueId(), --timeLeft);
                    }
                }.runTaskTimer(SpaceRaiders.Companion.getPlugin(), 20, 20);

            }else{
                //Hasn't expired yet, shows how many seconds left until it does
                p.sendMessage(ChatColor.RED.toString() + timeLeft + " seconds before you can use this feature again.");
            }
        }else{
            sender.sendMessage("Player-only command");
        }

        return true;
    }

}

 

(Register the command executor)
As you can tell, it seems very simple. The main part of this section is that it decreases the time left before they can use the feature again every second, in the BukkitRunnable task timer. It will work just fine as it is now.

This method, however, has some major issues. For one, you should always avoid using runnables, as async tasks will create a thread for each task. Second, this means if you have several hundred players online, you will have the map updating many, many times a second (assuming the players are using it). For minigames with multiple cooldown features, there can be as many as a hundred tasks running at once, and it can become quite a mess internally.

One of the largest drawbacks, however, is that you can only track seconds with this method (at the smallest). You can't track anything smaller, and if you wanted to you would have to change the time unit to 1/10s of a second or less, and it would need to be updated 10 times more often.
 

Method #2: Using Timestamps

Rather than updating a variable every second or more, you can actually just save the last time a player used a feature, then subtract it from the current time to get how long ago the player used the feature. From there, it's simple to make sure it has been more than x time. It looks something like this:

if (current time) - (the time the featured was last used) > (delay) [do feature, update last used time]

For accurate time tracking, we can use a feature in programming known as a timestamp. Timestamps are just like what they sound like - a stamp of the time it was used at. The most accurate type is to use System time milliseconds. Basically, the timestamp is in milliseconds. More technically, how many milliseconds have passed since January 1 1960 (known as epoch). You can use the function System.currentTimeMillis() to get the current timestamp in milliseconds.

We'll use the CooldownManager from earlier, with two changes. int (or Integer) type can't store a variable of that size, millisecond timestamps are stored in Long type variables. Simply replace occurrences of "Integer" or "int" with "Long" in the manager class. Second, instead of returning "0" if the map doesn't contain the cooldown timestamp, we have to use Long.valueOf(0):

return (cooldowns.get(player) == null ? Long.valueOf(0) : cooldowns.get(player));

With this method, our CooldownCommand class should look like this:

Code (Text):

public class CooldownCommand implements CommandExecutor {

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        //Player only command
        if(sender instanceof Player){
            Player p = (Player) sender;
            //Get the amount of milliseconds that have passed since the feature was last used.
            Long timeLeft = System.currentTimeMillis() - CooldownManager.INSTANCE.getCooldown(p.getUniqueId());
            if(TimeUnit.MILLISECONDS.toSeconds(timeLeft) >= CooldownManager.DEFAULT_COOLDOWN){
                p.sendMessage(ChatColor.GREEN + "Featured used!");
                CooldownManager.INSTANCE.setCooldown(p.getUniqueId(), System.currentTimeMillis());
            }else{
                p.sendMessage(ChatColor.RED.toString() + TimeUnit.MILLISECONDS.toSeconds(timeLeft) + " seconds before you can use this feature again.");
            }
        }else{
            sender.sendMessage("Player-only command");
        }

        return true;
    }

}


 

Already much shorter, and the variable is only updated when the feature is actually used!
You'll notice I used a Java util method you may not have seen before - TimeUnit. TimeUnit is extremely helpful, especially if you don't want to convert time units yourself. In the above example, we used TimeUnit.MILLISECONDS to tell TimeUnit the input variable will be in milliseconds, then used toSeconds() to get the output in seconds.

With a bit more math, you can convert to hours, subtract the hours from the initial variable, then convert the remainder to seconds. It does take some playing around with to get it down to perfection. There may be some available libraries or functions by other users that does this for you, however.

Making Time Calculations with Java Timestamps: The best performance-friendly solution to cooldowns

Awhile ago, while trying to become more active in the Spigot community offering help and discussing different methods of accomplishing things, I email subscribed to the Plugin Development section. I now get an email for every post, which occurs atleast once every few minutes. This means I'll probably have to get a new hard drive months before I normally would've, but atleast I can catch posts that are intriguing or spark a train of thought in some way.

For some strange reason, atleast one post a day is someone trying to add a cooldown effect to some tool or ability - basically, a player must wait x seconds before being able to use a feature again. 

 People don't seem to be able to use the search feature on the Spigot Forums before posting.

People don't seem to be able to use the search feature on the Spigot Forums before posting.

I can't help myself from responding to them as I see them, so instead I'm making this handy-dandy post with everything you need to know about how to create cooldowns, common pitfalls to avoid, and case examples.

Option #1: Repeating or delayed tasks

This is what I see getting most suggested after using timestamps. Basically, when the player uses the feature for the first time, a variable is set putting a player's UUID and the amount of seconds until they can use that feature again into a map, and a repeating task is started using Bukkit's Scheduler. In that task, the variable is decreased by 1 every second. If the player tries to use the feature, it will get the seconds from the list and if it's more than 0 it'll tell the player it has to wait <x> seconds. 

Why this is an awful method

When using countdowns of any kind, it's always tempting to use repeating tasks. It looks like it makes sense, right? In reality, it's not very performance friendly. First, it's not a good idea to have too many tasks running at a time, as a thread is created for every task. Second, you're changing a variable every second. That doesn't affect performance too much, but there are methods that are much more performance friendly. The main issue, though, is that tasks are just a little weird to deal with anyway. They need to be cancelled when no longer used, and a whole class is needed aswell, with a reference to either the task ID or it's actual object (thought it can also be cancelled from within the task itself). Using tasks should be a last resort, they just aren't a very code-clean method.

Option #2: Timestamps

The only reason you don't see timestamps as a solution to time tracking is that they can be a little difficult to wrap your noggin around the first time you hear about it - it's a little less beginner friendly, but much, much cleaner once you get the concept.

What are timestamps?

Timestamps are very simple by themselves. Simply put, it's the amount of milliseconds that have passed since January 1st, 1970. It's used by all systems. For example, your system clock runs off of that timestamp, and simply translates that into whatever format it requires. You can get the current system timestamp by using System.currentTimeMillis(). As the variable won't fit in an int type variable, it must be stored as a Long.

How it works

When a player uses the feature, their ID and the timestamp at that time is stored in a map inside a manager class. When a player attempts to use the feature again, you can use the equation <currentTimestamp> - <lastFeatureUseTimestamp> to get how many milliseconds have passed since the feature has been last used. From there, you can convert that into whatever time format you want to check it against the required time before the player can use it again.

In order to make time conversions easier, Java has a util class called TimeUnit. To convert milliseconds to seconds, for example, you can use the method TimeUnit.MILLISECONDS.toSeconds(<ms>). 

As you can tell, it is very performance friendly, so much more so than the previous method with repeating tasks. The variable is only set once, and it's even only checked or changed when the player attempts to use the feature. 

Potential issues and how to fix/avoid them

The only issue with this method is that it becomes a memory leak. It's very easy to solve, however, with these two fixes:

  1. On PlayerQuitEvent, remove them from the cooldown manager map
  2. If they use the feature and the cooldown has expired, remove them from the map

You'll notice how much easier it is to handle cooldowns, and with this method you also have the option to display it in whatever format you want.

Google Analytics Integration with Minecraft Networks

 Analytics data for a BungeeCord network averaging 15 online active players.

Analytics data for a BungeeCord network averaging 15 online active players.

I recently went through Google's Beginner and Advanced Google Analytics courses, then went on to get a certification for Google Analytics. In the process, I learned the power of Analytics and some of it's API features which I wasn't aware of previously. 

Google Analytics has a few different APIs for different purposes. By default, GA tracking code works as JavaScript that is loaded by the client went visiting a website. When the code is loaded, it sends page hit events (among other data) from the client to GA. That's how the most basic tracking works. However, there are cases where you don't have access to the client, as in the case with video game clients. You do, however, have all the info you need (session time, event hits, etc). Designed especially for such occasions, Google has a fairly simple HTTP API called the Measurement Protocol for GA.

It's extremely simple, and doesn't require any kind of authentication. Send a request to the endpoint with the tracking code and hit type, and it'll get processed by your GA property. 

Because it's so simple, I wondered how it might be useful to integrate with Minecraft Networks. Think about it - players are equivalent to users, pageviews to servers on a network. If you pass a player's UUID as the identifier for GA, you can also track new vs returning players and even bounce rates! That's just the tip of the iceberg, however.

Using the same measurement protocol, you can also record events from a player. One very useful event, for example, is the server vote event. This occurs when a player votes for a server on a server list. Combined with goals, you can then track what percentage of players vote for the server. If you add a label to the event, you can also track which voting sites are the most popular. 

Another useful goal are donations/purchases on your network. You can track the conversion rate - what percentage of active players make a purchase in your store - and which ranks/features are most popular among players. 

One more less obvious feature that several network owners requested was the ability to track player-community engagement. At the most basic level, you can see how many players interact with the community (by the amount of chat messages they send), especially useful if you segment new players only. If you have a high bounce rate (70% or more) and low to none new player engagement it could mean players feel foreign to the community or don't feel welcome.

An obvious question at this point is, how is this useful
As with website Analytics, it's not terribly useful on it's own. However, when paired with changes you make, it's very useful. One of the most common issues with a community not increasing is that the bounce rate is very high - players quit without really playing anything. Many networks get a new user nearly every hour, which means between 20-40 new players join every day. And yet, the average player count doesn't increase (or increases only very gradually). This means there is a very high bounce rate, most servers I play on see about 90% or higher rates. And yet, they work hard to increase the server rank on vote lists and even spend money on advertising. If they managed to decrease the bounce rate to even 50%, they could see an increase in average player count of ~10 players every day - a large increase for Minecraft networks. 

As with websites, people with a very short attention span - according to recent studies, about 8 seconds before we lose interest. That means you have 8 seconds to grab the player's attention with something immediately playable. Most networks have a large, fairly empty hub that looks great design-wise but does not compel the new player to make a decision within 8 seconds. Instead of a large hub, networks can see a decreased bounce rate by immediately jumping the new player into some sort of interactive story or a call to action. 

With Google Analytics, you can make such changes to the new player experience, then track the difference very easily. At an advanced point, you can even use A/B testing to find out which new player experience system works the best

 

I've already created a Google Analytics tracking plugin, and convinced my friend and the owner of a small network called ClownerCraft to install the plugin for testing purposes. It recently went active, and has been working very well. I also discussed using this plugin for larger networks (~80+ average players) with a developer friend, and he was so attracted by the idea he went beyond installing the test plugin on the network he works for to getting feedback from other network owners. I hope to increase the potential for this integration plugin, and in the near future it may see use on many upcoming networks.

You can check out the source code for the BungeeCord network plugin in it's current state on my GitHub account.

Programming Minigames

Every minigame I make are very similar internally.

Each minigame has a Game class, which has a game loop and methods such as addPlayer(), removePlayer(), startGame(), etc. Minigames normally have the following:

Game loop: This is called every second. It's used to track things like the countdown, or even checking if the game still has enough players to keep playing.

Add or Remove player methods: These are used when you want to add or kick a player from the game. When you add the player, it saves the player's inventory, location, exp, hunger, and health to be restored once the game has ended. It then clears his inventory, then adds any items needed (armor, weapons, etc). It then uses the sendMessage method to notify users ingame that a player has joined. This method is normally called when the player sends the join command, or when they interact with a join sign.

Send Message: This one is simple. In fact, it's only 3 lines. It takes a String as an argument, and sends a message with a specially colored tag with the name of the game to all players along with the String argument.

End and Start game: These methods control when the game starts or ends. The Game Status is an enum, typically GameStatus.WAITING or GameStatus.INGAME. These are used with listeners. For example, if I don't want a player to be able to move unless the game has already started, I could just cancel his movements if the game he is in has a status of WAITING. The Start Game method sends a chat message to all players, and sometimes executes a bit of code when deciding teams or giving special items depending on the team. A good example of this is when I made my Infection minigame. Two out of all the players are selected to be infected when the game starts. It's also then that they are given items depending on whether they are infected or not. The end game method is used when the game has ended (not enough players, or all players eliminated, etc) or when the server is stopped. This one gives back the player data saved during the AddPlayer method and resets the countdown timer and GameStatus.

As well as the Game class, I also have the GameManager. This contains some useful functions, such as getGame(ID). When a new Game instance is created, it is registered with the GameManager. When registered, it goes into a list of games. This list is accessed by the Main class, which then calls a doSecond() method in every Game instance. The GameManager also has functions for getting whether a player is in a Game, and even getting the Game a player is in.

Launching a Minecraft MiniGame Server

For a while now, I've been working on setting up a server for someone and making coding minigame plugins. The server was finally opened yesterday, and I'm satisfied with the work I did.

The server has one main minigame, Infection. This is a simple game where there are two teams; the infected, zombies, and the humans. The infected have to try infecting the humans, putting the humans on the zombie side. The humans have ranged guns, with no melee, whereas zombies merely are super powerful but on melee. This creates an interesting combination, where the humans have to shoot the infected before they can get near enough the infect.

The humans can use three guns; a shotgun, which is really bad accuracy (only usable at less then 5 blocks range) and a high recharge time (meaning you only get one shot) but can kill zombies in one hit, a sniper rifle which can kill zombies immediately if you get a headshot, and a machine gun which fires tons of arrows at once with no recharge, but low accuracy/power.

Infection is probably the largest plugin I've worked on, but not the first minigame. The first minigame plugin is called Banana Tag. In real life, Banana Tag is a game where all players can tag each other. Once tagged, the player has to crouch down, meaning he/she cannot move. To become untagged, the player who tagged them must be tagged or they can try tagging someone who gets near them. I used the basic mechanics and put them into a Minecraft minigame. To tag a player, you need to hit them twice. Once tagged, they sit down on the ground and cannot get up. The winner is the player who has tagged every player.

Beam Interactive with Minecraft

Beam.pro is a fairly new streaming service, similar to Twitch.tv. It allows people to stream their gameplay for viewers to watch realtime, and interact with via chat. Beam was released with less delay between the client and viewers, as well as a thing called Interactive mode.

Interactive mode allowed the streamer to setup a control panel of buttons and joysticks, as well as track viewers mouse movement on the streaming screen. Then, they could allow the viewers to interact with the streamer via the buttons. The most common use is in Minecraft. One button might teleport the player to a random position close to where they were, while another might give him a random item, useless or rare.

In order to limit the amount of times these buttons could be used, Beam also introduced their own kind of currency, or points. These points could be used on the buttons, while earned overtime by watching streams or streaming themselves.

Currently, though, Beam Interactive is in beta. This is because in order to use it, you need programming knowledge to connect to Beam's API and receive data about the buttons. Then, in order to interact with Minecraft, you need to use plugins or mods to then change the Minecraft world. Beam did release an interactive app for Minecraft, but only with set controls and commands.

I decided to make a Beam Interactive Minecraft mod. It would allow you to set Minecraft commands to each button. Now, one command doesn't seem like it can do a lot. However, with the /setblock command, you could easily trigger tons of command blocks, making the possibilities endless.

After getting lots of help from Beam's developer channel, I was able to make a simple mod. It got the IDs of all the buttons, meaning you just needed to set what they did in a text box. Then, you could load and save the control layout, with up to 3 save slots. That part was my favorite, and my first time implementing a save/load mechanic in any program.

The mod isn't available for download just yet, but it should be soon in the next few days. You can check out my Planet Minecraft member page to see when I release it.

Minecraft Modding: Storing custom NBT data

So for a secret idea for a mod, I was learning how to store data on a player. The best way to do this that I know of would be to use NBT data, which is saved on the world per player. NBT data can include many things about the player, like health, potion effects, hunger, strength, etc. It is more commonly used in entities, for things like velocity, age, speed (for horses). You can often see this when you use the /summon command for mobs with custom data.

I was having lots of trouble, starting with getting the NBT data of a player upon joining a worldserver (single or multiplayer). If the player didn't have my custom data stored on him/her, it would create the data with a default value. This is almost only used when a new player joins the worldserver. However, the function that I was using (player.getNBTTagCompound()) was giving me a bit of trouble. Every time I tried using the hasKey() function (to test whether the player has a certain bit of data), it crashed. I led this down to the fact that the getNBTTagCompound function was actually returning null. To see why, I looked at the vanilla function for this.

Guess what? The function had a single line of code. "return null;". WHAT?!? Why on EARTH would you have a function return null, unless you purposely wanted it to crash the game. It might have been there because the Mojangsta working on updating that found too many dependencies on that function and lazily didn't fix the errors by updating the code; he simply made the function return null. And, as it turns out, that didn't cause any problems. Until now, when it was extremely misleading.

Anyway, I found a function called readFromNBT() which accepted an NBT tag. I assumed from how other people used this function that it would basically input the NBT tag I put into the function with all the data values of the player. This would mean creating an empty NBT variable, then using readFromNBT to input it with data.

As it turned out, I was half right. There was another function, writeToNBT() (again, taking an NBT tag variable) which I assumed would apply the NBT tag to the player. Like I said before, I was half right. Every time I joined the world, it set me to 0,0,0 coordinate position. It really confused me. Then, suddenly, I facepalmed. Of course, duh. I got the functions mixed up. The writeToNBT() function would write the player's data to a variable, while readFromNBT() would take the data of the variable and write it to the player.

I haven't yet gotten a chance to try it out, but I'm looking forward to it tomorrow.

Scarab's Missing Furniture Mod

So about a week ago, I decided to get back into modding with 1.8. This time, I followed the tutorials on YouTube by MrCrayfish, and it was pretty simple. He didn't get into too much detail, but I'd already had some experience with 1.6 and 1.7 modding already.

That night, I had the idea for a furniture mod. Not just any furniture mod, and not one that copied mods like MrCrayfish's and other people's famous mods. Instead, I would add the small things that they missed, as a sort of addon to the other mods. In 3 days, I got 2,000 downloads and 5,000 views, as well as lots of comments.

The mod started when I was building a Minecraft house. It was a lakeside house, and I was just building the back patio over the water, when I realized there wasn't anything to put on it furniture wise. It needed a deck chair, which wasn't in MrCrayfish's furniture mod. Solution? I created my own. Then, I added a monitor, and an espresso machine. Nice little decoration blocks for around the house. It started with about six blocks, which were just plain models with no function. I released it on the Minecraft Forum, but got no response and only a few downloads. Then, I put it up on Planet Minecraft. Checked back about an hour later, and I had more then a hundred downloads. I immediately realized that I had better update it with more function and features, while it was still popular.

I added coffee, function to the espresso machine, video on the monitor, a ceiling light, a 3D printer, and lots more. Every day since I've released it, I've managed to release an update.

Probably my two favorite parts about the mod is the 3D Printer function, and the recently added update notifier. The 3D Printer function is simple. Just right click the 3D Printer with printer filament, and you get a random player's head. It chooses the head from a list, randomly. This list is actually stored online in a Dropbox folder, and is downloaded every time the game is started. I also added an option for people to donate, and get their username to the list of players that it can choose from.

The update notifier is equally simple. In another text file on Dropbox, there are four lines of text. The latest version number, the latest update name, the latest changelog link, and the direct download for the latest update. When you open a world, it will check if the version in the online file is later then the mod's own version. If it is, it sends a chat message notifying the player of a new update. It includes links to the changelog and download, so usersdon't have to go find the mod page again.

You can view this mod by clicking here.

Pi Wars Podcast Episode With The Raspberry Pi Guy

For basically the first time, I got to talk with someone on my podcast, Kids Who Code.

And of course, the first person I talked was the well-known Raspberry Pi Guy. It went very well. We talked about Pi Wars, an event in Cambridge, UK where Raspberry Pi powered robots compete in (non destructive) challenges. He talked about some of the challenges, like the proximity detector challenge where your robot has to get as close to a wall as possible without actually touching it. He attended the event (he didn't participate though) and told me about some of the robots that he had seen and what they did. It sounded quite interesting. You can listen to it here:

Top 3D Printing Problems (Check For Them Before Starting a Print Job)

When 3D printing, it is NOT going to be easy. It's not as simple as loading the 3D model, slicing the 3D model, and printing the sliced model. There are many things you have to look for before starting a 3D print, such as ambient and bed temperatures, or Z Calibration. Here are a list of the top <some amount here> problems!

  • Heat bed is too cold: When the heat bed is cold (or at least not hot) 3D prints tend to warp. Warping occurs when the bottom of the print cools faster then the top, and expands. A hot heat bed keeps the print on it warm on the bottom, where it would typically get cold from the ambient temperature of the environment.
  • Heat bed is not level: This is a rare problem, and shouldn't normally occur. However, sometimes you may notice that the nozzle is printing too high above the bed and at other places it is scraping the bed. This usually means that the bed is bent in such a way that on end of it is bent upwards while the other end is bent downwards.
  • Ambient room temperature is low: When the room temperature is too low, it will cool the heat bed. Heat beds are usually very weak anyway, and won't stand up to a cold room.
  • Not enough adhesion: When your prints are coming off of the bed during printing, it probably indicates that you do not have enough adhesion for the print to stick to the (heat) bed. When adding adhesion, you will need to use some sort of tape (so as not to dirty up the actual metal bed).
  • Z Calibration is wrong: You will notice this when either the nozzle is scraping into the bed or it is too high above it and the plastic is not touching the bed enough. You have to calibrate it every few weeks, to get perfect prints. Usually, you have to get this correct within 0.05 of a millimeter.
  • Bigger 3D Prints Are Warping: This is common, and mostly happens because the middle of the heat bed is where the heater is, and is a lot hotter then the outer edges of the heat bed. Also, it has a lot more space that can be hit by a cold draft.
  • Under or Over Extrusion: You will notice this when the 3D prints have bits of plastic sticking up above the current print layer, or plastic wrapping around the nozzle. This means it is printing too much plastic at a time. For under extrusion, you will see very thin wallsthat aren't even very solid.

Pragmatically Programming

Programming and life are two very different things, right? When you do programming, it's either yes it works or no it doesn't. If it doesn't, you go and fix it. You program something, and there is always one way to do it.

As it turns out, this is not actually the case. Programming and life are actually very similar. When you do programming, there might be two ways to do something. And, when having a team of programmers, it is even more important that you code things CORRECTLY. Sometimes, you might get the end result you wished for, but your code is incredibly messy that anyone trying to edit it would be completely lost in it all, and even you yourself might find it difficult to fix problems. One good example of correct programming is going by the DRY principle. DRY stands for Don't Repeat Yourself. While this may seem like a hard principle to get wrong, you may be finding yourself copy-and-pasting code or writing similar methods. The opposite of DRY code is WET code, which stands for We Enjoy Typing. Don't write WET code. Whenever possible, write methods and use variables.

For example, when writing a Minecraft plugin, you would probably want the text "[CoolPlugin]" (or whatever the name of your plugin is) before each message it sends to the server, like "[CoolPlugin] ScarabCoder left the game". You could make it do something like:

server.sendMessage("[CoolPlugin] Player left the game")

However, you will find you are repeating yourself if you write this way. For every server message you want to send, you will be writing "[CoolPlugin] ". Sure, it might do what you want, but it'd be really, really messy. Imagine the horror you would have to go through when you wanted to change your plugin name from "CoolPlugin" to "AwesomePlugin". Search-and-replace? You would probably still miss something, or probably replace the wrong text. Instead, use the obvious answer; variables. That way, if you wanted to change the plugin name, you could just make a global variable (a variable that is accessible from any part of the program. Languages like Java use this) that would equal to "[CoolPlugin]":

pName = "[CoolPlugin] "
server.sendMessage(pName + "Player left the server")
server.sendMessage(pName + "Player joined the server")

See how much simpler that is? But wait, you are still repeating yourself! You are writing "pName + " before each server message. It's time to create a method. Methods allow you to do things like "sendServerMessage(message)". You can accept inputs, and it is really easy. Not only that, but you could also do something like "logAlert(message)" or "logError(message)", which would send a server message in different colors (red for error, orange for alert, etc). Example:

method logError(message){
  server.sendMessage(color.red + pName + message)
}
logError("server crashed!")

Woooaah! You just cut down the amount of characters you are using by a ton, and made it so much easier to configure your plugin. If, for example, you ever wanted to add another prefix to your errors, you can add that simply in the method.

 

This also means you shouldn't be writing "hacky" code anymore. Hacky code is code that you are using shortcuts or code that might be a bit sketchy and may break with newer versions. You shouldn't be writing this kind of code, and make sure you keep it far away. The temptation to take small shortcuts like this without even checking for another way gets strong, believe me.

Buycraft

Many servers actually run off of player donations, and some people are even able to live off the extra money that doesn't go into to the server! But how does this process work?

You may have seen shop pages for servers. If you haven't they typically look like this (EcoCityCraft's Shop). If that seems familiar, it should. In fact, almost every server webstore will look similar to this, this, or this (HiveMC, ClownerCraft, and The Chunk store pages). They are all powered using a service called BuyCraft. BuyCraft allows you to setup a webstore, and then send custom commands to the server when you buy a rank. For example, I could create a "package" (or virtual product) that, when bought, would send multiple server commands to set a player's rank, give him ingame money, and broadcast to the server.

It has many, many features, and extremely customizable. Not only can you edit the default CSS of multiple themes, but you can even edit the HTML too! This means that you can have a completely custom store that makes easy updates every time you add a package. Another cool feature is that you can have subscription packages which can charge the buyer after a custom time, and can send commands each time. This could work for temporary ranks that you would have to pay a monthly subscription to, and, when the subscription expires, would demote the player back to the previous rank.

Buycraft is free, though with many limitations unless you upgrade to a different plan. For example, the free plan only allows one payment gateway (the method through which you receive payments) and five packages. The next plan costs ~$6 a month, and allows you to have unlimited packages, categories, and gateways, but only allows you to earn $2500 or less per month. The final plan has many more features for huge servers, and costs ~$30 a month.

I setup a quick webstore, partly for the idea of Mine Monthly Events that I had, and partly to test some of the Buycraft features. Currently, the packages actually do send commands to the server, but the server itself is a local one (you can't join it). You can visit it here.

Mine Monthly Events Idea

I haven't been using my server subscription with CubedHost, and I had to cancel it. However, I recently had the idea of doing events similar to the StarWars event on May 4th. I had quite a lot of people signing up for it (nearly forty people), and it was lots of fun. I enjoyed doing it, and would do it more if I could get the money to pay for the server. And, due to the fairly large amount of players on the server and probably because there would be lots of explosions and mods, I would have to get a server with a large amount of memory to keep down the lag. For the Star Wars event I used 6GBs of RAM, and it cost $40 a month. There was no lag at all on the server, so I could probably have done with 4GBs.

I had an idea that would both let me hosts events, and take care of the cost for paying for the server. I could host two events every month (or, if I couldn't get enough people, just once a month) and only allow people to play every other time. If they wanted to play every time, they could buy a "ticket" for just $2 USD and use that. That way, probably at least half of the cost of the server would be payed for. If I could set up a subscription service, I could be hosting the server for free (of course, I would still have to set up the events, but I enjoy that).

There are also many events I could host, all of them would probably be about some famous (family friendly) movie, such as Lord of the Rings or Star Wars. I could repeat certain themes but at different places, and maybe even follow some of the battles in these movies.

PiPad - A Raspberry Pi Tablet

Recently, the Raspberry Pi company released the long awaited Raspberry Pi Official 7" touchscreen. Almost as soon as I saw it, I knew I wanted it. I already had the Adafruit Powerboost 500, and I immediately had the idea of creating a Raspberry Pi tablet.

I have a 3D Printer, so I was able to find a nice 3D model on Thingiverse and quickly printed all of the pieces. When putting them together, I had to use ABS glue to glue some of the pieces together, and then used several screws to put together the rest. It isn't perfect, but it is solid enough. I used the Adafruit Powerboost 500 and a battery, and also a short micro USB cord.

I haven't done anything software wise yet, but I definitely plan to. Probably I'll be using Kivy, because it is perfect for touchscreens (though PyGame would probably be easier to code). Several of the Python games that came with the Pi work with the touchscreen (the memory puzzle and slide puzzle), and my 4-year-old sister loves to play both. It can also play Youtube videos at a nice ~45fps, so it would do well as a media player. I'm looking in to some sort of Youtube downloader so that I can watch videos wirelessly.

Here is a video I took (sorry for bad quality, was using a phone at the time :D):