Why I have started using Java over Kotlin

I've been using Kotlin regularly for all the projects I would normally have done in Java for the past six months at least. Kotlin is a JVM programming language which compiles into Java bytecode. The difference is how the syntax is written before it's compiled. Kotlin basically removes the repetitive areas in Java (notably getters and setters), enforces programming conventions, and gives a slight performance boost due to the default ways it resolves functions. It's syntax is very similar to JavaScript, and in fact can "compile" (convert) into JavaScript as well as JVM bytecode.

After doing a few more projects for other clients, though, I've encountered a few flaws with using Kotlin as a practice. The main flaw (which should've been fairly obvious at start) is that clients don't like it. Sure, it might mean their project gets delivered quicker and bugs are easier to fix (by the original author). But for large projects (gamemodes for example) or networks which need to constantly adapt, Kotlin is discouraged. This is because only a small percentage of Sipgot developers actually know Kotlin, thus making it difficult to find a developer willing to fix bugs in the project if the original author is no longer available.

Another annoyance are the compile times. A project can take as many as 30 seconds to build, where a Java one can be done in under 5 seconds. On top of that, projects using Kotlin also need to have the Kotlin library available at runtime. This turns a normally 2kb project into a 4mb one. 

Finally, proficiency in Java beats the same in Kotlin. Even if they aren't programmers or know any programming, most people know what Java is. Less so Kotlin, and attempting to explain it just doesn't work.

Structures, the Vanilla Minecraft Schematics

Whenever someone wanted to share a Minecraft build, it was done by either sharing the Minecraft world for someone to load up and look around at, or is a schematic file for pasting into an existing world. Schematics were largely more popular, since servers could use it in combination with WorldEdit or MCEdit to paste it into their existing server world. The schematic file format has been around for a very long time, the first occurrence I can find in MCEdit's source being in October 2011 (though it probably existed before that).

Schematics were never endorsed by Mojang, so they required 3rd party tools to use. There isn't any specific rules of what a schematic should be, though they were generally decided by how WorldEdit or MCEdit used them. The current documentation of the format can be found on the Minecraft wiki. It includes a lot of the different fields added by community tools or outdated versions of MCEdit.

Around when 1.7 was released (2013), Mojang started to move away from numeric IDs deciding what blocks existed. This was mainly due to the fact there was a limit of how many different blocks could exist, but also because it's generally bad practice to use number IDs for data. This meant they moved from "1" being a stone block in the world to "stone" being a stone block. They started enforcing this with the vanilla commands, despite the fact numeric IDs were still used internally. In 1.12, you were no longer able to use numeric IDs in commands, and in 1.13 what was referred to as The Flattening happened. 

In combination to numeric IDs, pre 1.12 versions used data IDs. They were used when there was a block type, but it had sub types. For example, you had the wood log block, but there were about six variants of that block. So for oak wood, you had wood:0, birch had wood:1, etc.In 1.13, however, they removed all of these sub-type IDs and replaced with their own dedicated materials. This meant instead of wood:0, you had oak_wood, birch_wood, etc. They then added tags to these groups to make them easily discernable without having to do a ton of extra checks.

In 1.9 (released three years ago), though, Mojang added the officially supported and used Structure file formats. They were used internally to generate some of the natural structures, for example the End Cities and end ships. At the same time, they added the user-accessible Structure Block, which allowed players to select and save areas to a file and load it up again later. Despite the fact they were officially supported and part of the game, it never seemed to catch on and seemed to be largely ignored. WorldEdit didn't add support for them, and Minecraft build databases didn't support structures as a download option. 

With the new 1.13 update removing numeric IDs, hopefully Structures will be making a comeback. The file format is clear, and supports things like entities and block NBT data. One of the main reasons it isn't really used in Spigot plugins (that instead use schematics) is because no maintained libraries support them. In an effort to fix this, I'm trying to contribute to the Spigot project (and exploiting the fact that it's open source) by adding them into the Bukkit API for use by plugins without 3rd party libraries.

CraftBukkit, Bukkit, and Spigot Differences Explained

One of the confusing things I encountered whenever trying to look behind the scenes of the Bukkit API is what CraftBukkit, Bukkit, and Spigot referred to. Recently I've been looking at the source a lot more, and am even contributing towards it as well.

Years ago, Bukkit was DMCA'd by one of it's own developers. A DMCA (Digital Millennium Copyright Act - yes I had to Google that one) is similar to being taken down for piracy, but usually applies to stolen code. Technically nothing was stolen, since the code was under the GPL license, but it didn't stop the takedown from going through, stopping Bukkit development. Development attempted to continue, but it was later found that Mojang owned Bukkit, and they shut it down.

Because of the licensing at the time, you could still fork (make a copy and independently develop) Bukkit and continue development. Before it was DMCA'd, Spigot had existed. It's mission was to make it more performance friendly, but after Bukkit went down it became the most popular and basically the only active development of Bukkit.

When someone refers to the Spigot API or Bukkit API, they usually mean the same thing. Really, though, it's the Bukkit API being developed by the Spigot team, so it's still the Bukkit API. 

Bukkit is the interface for CraftBukkit, the implementation. Bukkit provides the function parameters and documentation, but on it's own are just empty interface functions. The purpose of keeping them separate is that Bukkit only changes with feature changes and then very rarely (usually not breaking anything depending on it every update) whereas CraftBukkit must be updated for every update to support new Minecraft changes. 

Remote Debugging Spigot Plugins with IntelliJ

The most useful discovery I've ever made in programming wasn't actually a programming feature, but being able to use the debug features present in most IDEs. Debugging is one of the most difficult and mind-numbing tasks in programming, and makes up a large part of the programming process.

Debugging in the IDE usually revolves around something called breakpoints. In order to setup your IDE to work with a running program (the Spigot server for example) you simply have to add a few arguments to the script you use to start the server. In your IDE, just create a new Debug Run configuration and provide the port set in the startup parameters. You don't have to recompile your plugin to use any of the debug features.

Breakpoints allow points at which the server should stop at (freeze). In the IDE, data for that "frame" will appear, showing you the values for variables in the source at that breakpoint as well as in it's own window. This is especially useful when you don't know the specific issue you are having, and saves time (as opposed to making minor modifications at near random until it works). 

You can also "step" around frames. A frame is a set of data for the level you're looking at. For example, if you have a function calling another function which does a calculation (a + b for example) you could place a breakpoint right before returning the function result. When the program reaches that point, it will stop and the IDE will provide the values for the variables as they appeared during runtime. The frame in that case is inside the function. If you wanted to know where the function was being called from, so you could get the context, you can step out of the frame to the function that's calling it. You will then get provided with all the variable data in that function.

One of my favorite features is being able to use breakpoints in libraries, without having the original source. For example, if the player was being healed from some other plugin or source and you wanted to know why, you could add a breakpoint to the Player#setHealth() function in CraftBukkit (as decompiled by the IDE). Whenever it's called by any plugin, it will halt the program. If you have the plugin calling it added as a library you can step out of that frame and find out what the execution parameters or requirements are for that plugin to execute the function.

Another cool features is being able to update the classes during runtime. If you wanted to change something small, changing a -1 to a 1 for example, you could actually update that part of the source on the server without having to restart the server or program. It is limited, though. You cannot change any class declarations (class names, function names, parameters, class/global variables, etc). It does work well for quick testing, though. You could switch out a URL to an API endpoint to a test one (provided by something like Postman) if you wanted to test it with different endpoint results.

Finding Malicious Code in a SpigotMC Premium Plugin

As part of my job as resource staff on the SpigotMC forums, I handle resources (plugins) being reported. Most commonly they will be someone "stealing" another resource and simply reposting the same file (and sometimes even the same description) as another existing resource. Sometimes they will even report the original as the impersonation (though obviously their resource was published after theirs). Those resources are removed very quickly and the user warned (and if it continues, banned).

When checking out these reports, most of them require decompiling the plugin jar file to verify it is actually stolen or contains malicious content. You can also sell your plugins on SpigotMC (the limit being around $20 per copy), and there are specific rules for that. Before you can post your premium resource (as they're called) you must have at least 40 posts and 20 positive ratings, as well as a few published resources. This means that only dedicated members of the community can sell their plugin, not just anyone looking for a place to make money. 

Then premium plugins must be approved by staff. The rules also don't allow generic plugins, in order to keep what's being sold as high quality as possible. Notably, KitPvP gamemode plugins are given as an example of what will be denied. KitPvP is a simple game that started several years ago. Players are given kits and drop down into an arena and simply PvP to death, to be respawned and drop down again. It based around kits, starting items with different gameplay types. Unfortunately, they were fairly easy to create as plugins which led to many of the plugins being sold doing the same things, so SpigotMC require resources to be original and innovative. 

Premium resources commonly are bought, then the copy given away on pirating websites. Nearly every remotely popular plugin has been pirated this way, and there isn't much the authors can do about it. In order to prevent authors from selling plugins than later revoking access to it's features, the premium resource rules state that plugins must work without an internet connection (cannot contact the author's servers for validation) nor should any features be able to be remotely disabled. 

One resource, a gamemode type resource, was reported because it had suspicious sounding text in the description that ran something like: "If you violate these terms, do not underestimate the power of Java". I didn't personally handle the report (another staff member got to it before me), but I went ahead and decompiled the plugin anyway out of curiosity. 

It turned out to be full of malicious code, though not intentionally so. First, it wouldn't work unless you had an internet connection (would disable the plugin). But then, it also gave special abilities to players on a contributor list. Remotely, he could also delete every plugin and it's data running on the server (which is the majority of the entire server really). 

What was really strange is that he also created his own ingame GUI which allowed him to kick and ban any player on the server, as well as send back information about the machine the server was running on. The resource was removed.

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: