Spreadsheets, Minecraft and OCD organization…

Let me start out with HOLY CRAP TWO POSTS IN ONE DAY!? AFTER 9 MONTHS OF NO POSTS!? WOAH!! Am I crazy? Probably! Maybe not enough though…

So I found that I really enjoy using Google Docs spreadsheets. Well, I’d say use, but I think “abuse” is more the correct adjective here. Did you know that you can get 188000 rows, if you have only 13 columns? Well, it’s an odd limitation, but I found it! A workbook on Googlde Docs Spreadsheets can have only 5 million cells. That’s all sheets in a spreadsheet, not per-spreadsheet. It makes sense, memory resource limitations and all.

I’ve taken to using a spreadsheet for organizing all of the permissions for a small Minecraft network. When I say small, I mean 9 servers, 26 worlds, 10 “tracks” (groups of permission groups), 75 positions (permission groups), with an unknown amount of permission nodes for 98 plugins. The way I have my spreadsheet set up, is to use a row as section headers for the next set of columns. (If that don’t sound foncusing, let me explain)

The first row is, of course, my sheet header with each column labeled – because “A” “B” etc are not good names for data organization. I have this row frozen, so it’s always at the top. I also have the first and second columns frozen, so they will always be shown on the left side of the screen. These columns are Track and Group. I then have Columns “C”, “D” and “E” grouped under Group. These columns are “Prefix” “Username” and “Suffix” This was important so I can hide these columns now that I’ve completed that part of my job, without starting a new sheet, or removing them. Duration and Titles, “G” and “H” are grouped under Info, column “F”. Again, so the Duration and Titles columns can be hidden under Info. Columns “I” and “J” are “Server context” and “World context”, with World being grouped under Server, again to hide it. The next three columns, “K”, “L” and “M” are Plugin, Permissions and Negated Permissions. Yes, “L” and “M” are grouped under “K”. When I say grouped, this is a function in Spreadsheets which allows the grouped rows or columns to be folded or collapsed into the parent row/column. So with everything collapsed, I see columns “A”, “B”, “F”, “I” and “K” – and I can expand the section I need to focus on.

I’ve done this with rows as well. The first data row is the name of my first track, and as such A2 is filled in with that name, “Admin” (A1 being the label for the column in my header row, “Track”) For organizational purposes, I’ve left B2 empty, and went to B3 for my first “Group” entry. This allows me to collpase B3 under A2, without showing the first group, as it would be if I were to have used B2. This also allows me to free-up the rest of the row for track-specific data, such as Suffix, info, etc. I’ve done the same for the rows which contain an entry in the Group column, again so I can have group-specific data stored in that row. Moving to Column “I” or “Server context” I have again stepped the first entry in this column to the next row down. So, I4 is my first entry for Server contexts. And “J5” is my first entry for World contexts, as a “world” is a subset of a “server” I’ve continued this mostly-empty row organization with columns “K”, with each row having a plugin name. My first plugin is in cell K6. The next two columns will contain all of the permissions for that plugin in the same row however, L6 (first plugin’s permissions) and M6 (first plugin’s negated permissions) Row 7 will have my second plugin, permissions and negations, so on and so forth until I run out of plugins.

I have a nice nested effect going on with my rows, with the column to the left being the “header” for the cells to down and to the right. And when I collapse all of my rows, I see a nice list of all of my tracks. Then I can expand which track I want, and see the Groups within it. And expand the Group for which I want to modify or retrieve data from. At this point, I’m working towards well over 120000 rows, with 12 columns (The username column is only a placeholder, and is going to be removed) And so I’ll be looking at 1.4 million cells, with the vast majority of them empty, and not even visible at any given time.

But why so many rows, columns and thus cells? So, each plugin has it’s own permissions – some plugins give inherent permissions for all players, and some give inherent permissions only for those in the game servers’ “Op” file. Minecraft uses it’s own very primitive permission system for built-in commands. It’s archaic, non-granular, has 4 levels and various permissions within each level, with each higher level inheriting the permissions from the lower. But here’s the kicker, and why it’s archaic – Say I want someone to be able to kick a player, but not to build at spawn – well, with Minecraft’s Op system, that’s not possible, because building in spawn protected areas is a base level permission – kicking is the next level up. So, enter, and back to, Minecraft Permission Management Systems. I’m transitioning from PermissionsEx to LuckPerms. Various reasons, mostly due to LuckPerms having an active development team, and some functional technical reasons as well. I’m also taking the opportunity to build out readable documentation that my staff can access to assist with entering all of the permissions into LuckPerms, and for future reference for myself.

I seemed to have digressed a bit with that, so back to the question of why so many. First off, I have an unknown number of permissions. But let’s say the average plugin has 15 permissions (so have none, and some have much much more, so 15 is pulled out of thin air). Now, I have about 100 plugins. That alone means there’s 1500 permissions. Now, one plugin in specific has roughly 1500 permissions by itself. So, let’s say we have a total of 3000 permissions. Now, you may ask “OK, but that’s only 100 rows, as permissions for each plugin are grouped into the same row?” It’s not that simple. There is the potential for each world context (a world context is the number of worlds + the global server context, so n+1) having at least one entry for each plugin. There are a total of 26 world contexts, and several servers are only using a single context (global), so there’s the potential for even more. So we’re at 2600 unique potential permission rows. World context * plugin count. (I’m at 96 confirmed plugins, but may be adding a few more, so we’ll round off to 100 for this exercise) Now here’s the kicker: That’s per position. I have 75 permission groups (positions) So, 2600*75 is 195000 potential permission rows. Now, not all plugins will be installed on all servers, not all plugin permissions will be applied to every position (given or negated), not all plugins even have permissions, and there are some tricks to compounding permissions using * and built-in super-permissions (a permission which gives all the same functions as multiple other permissions) So it’s a LOT of permissions, data and work.

As someone who is very visually organizationally oriented, this helps to fully detail out the entire scope of the permissions on the network of servers. For me, at least. Ideally, this will also give my staff the ability to read the permissions per world, per server, per group and thus be able to enter the permissions into the new system for me. AND We’ll have a system-agnostic documentation that can be referred to and altered as needed in the future. It sounds extrememly convoluted and anything from easy. And it has been an absolute pain in the sphincter to set up. However, it’s use should be pretty simple, provided those who use it can understand multi-dimensional data storage. (spreadsheets with collapsable rows and columns) At it’s visually smallest, there will be only 11 rows and 5 columns. 55 cells, with 44 of them being empty. This is how each person should initially view this document. Each row and column can then be exapanded and collapsed as needed to navigate to the particular section and sub-section to modify or read.

In some respects, this is still easier than Windows Server 2003’s Active Directory. In others, I’ve completely rebuilt the entire framework of a Permissions Management System in a spreadsheet. For years, I’ve hoped someone would create an AD or OpenLDAP Minecraft plugin, but I feel the time for such an adventurous project has come and gone. Microsoft may be doing wonderful things with Minecraft still, but if we’re not already in it, Minecraft’s sunset period will be upon us within a few years. With the release of the right game, it could be even sooner. But what the developers behind LuckPerms has done is absolutely amazing and I hope they have written it in a way that LuckPerms can become game-agnostic and useful for other ventures in the future. It is already available for Minecraft Java Edition (Bukkit, Spigot and Paper); Minecraft Bedrock (for consoles/Win10) through NukkitX, a Bedrock server written in Java; Minecraft Forge servers (Also for Minecraft Java Edition, but different API) and I think another Minecraft server or two as well. But these things have two things very much in common: the base Minecraft game & Java.

At the top of this post, there’s a screenshot of the framework, with some sections collapsed, and some visible. For reference to this article only.

Linux, Java, Git and Maven…

Here, I will explain how to *simply* get a Java project with Maven compile instructions (pom.xml) on Github to your system, and compile it using Maven. This requires a few things. We’ll use Potato. You can fork this project with your own Github account, and then you can say that you’ve “Forked a Potato” (Seriously, it’s just a fun project with limited to no practicle use) We’ll be using Potato as our reference example project. It is Java, with Maven, on Github and will compile under Linux. https://github.com/AeSix/Potato

First, let me state that I use Ubuntu GNU/Linux distros. Life is too short to worry about getting everything installed “the hard way” – Ubuntu’s apt-get is, in my humble opinion, the simplest way to do routine software installs. I’ve built Slackware linux, ran through Fedora Core, messed with Gentoo and Suse, and various other distros, including Debian (Ubuntu’s papa distro) For everything I’ve ever needed, Ubuntu has provided much simpler than other distros. That may not be the case for everyone, however. So with that all said, I’ll be talking about “Linux” pertaining to Ubuntu GNU/Linux specifically. These instructions may be translatable to other Linus distros, to UNIX distros (FreeBSD, MacOS, etc) or even for Windows with varrying degrees of success. I won’t discuss these here though.

The first step, of course, is to procure suitable environment and install your OS. We’ll assume this is done. If it’s not, you’ll want to do that, after reading the rest of this. You’ll find specific instructions for your environment online, and so I won’t waste time here detailing that.

Next, you’ll need to install Java. This is a considerably more difficult process on any Linux distro, if you’re wanting to use Oracle Java (as opposed to OpenJDK), that’s as simple as
> apt-get install open-jdk
I prefer to use Oracle JDK, however that’s a personal preference. You can find installation instructions if you were to search for “Oracle Java Ubuntu webupd8” – there’s plenty of info on that and does not need to be duplicated here.

Once you have Java installed, you’ll want to get a Git client and Maven. Again, there are installation instructions online for each of these. I suggest Gitlab’s instructions, but DigitalOcean has some nice write-ups as well.

At this point, we’ll assume you can do these things:
login to your Linux user account, and perform commands with sudo. I highly suggest NOT using root user!
– Test your network connection:
> ping google.com
– Test your Java installation:
> java -version
– Test git client:
> git –version
– Test Maven installation:
> mvn –version

Assuming this all went to plan, you should now create your work environment. I suggest making a ‘dev’ directory under your /home/username, with a git directory under that. OCD organization!
> cd ~ && mkdir dev && cd dev && mkdir git && cd git && pwd
Provided this worked, you should see something akin to, with “yourusername” being replaced:
/home/yourusername/dev/git

Now all the setup is done, let’s clone us some code!
> git clone https://github.com/AeSix/Potato
> cd Potato && ls
The first command here will reach out to Github and fetch a copy of Potato from github.com/AeSix/ and create a new directory under git/ called “Potato” The git client will always create a new directory in your cwd with the project name as the new directory name. The second command simply puts us into that directory and lists it’s contents. Verify that the contents on your system match that of the repository you cloned from. If it does match, Congrats! You’ve cloned a Java Maven Git project!

Let’s build this project. This is what I *LOVE* about Maven, how simple it is! You’ll be addicted and wanting to compile github projects every day! (Ok, maybe I alone got a bit overly enthusiastic about Maven when I first got it working!)
> mvn clean install
That’s it! That’s all you needed to do! Of course, you *have* to be in the directory with the project’s files for this to work, and the project *has* to have a ‘pom.xml’ file. Of course, the project also has to be fully written, not broken, and compatible with your version of Java and potentially your OS (Very old OSes may not have some functions that newer Java projects require, but then your Java version would be subject to these and you’d never get a new enough Java installed to even build with much less run the project with)

Oh! You actually want to run the project? I guess I can tell you where the compiled jar is.
You should still be in /home/yourusername/dev/git/Potato – so do
> pwd
and confirm you are. If you’re not, then something went awefully awry and you should figure that out. Let’s assume there’s no problems though. Now do
> ls
You should now see a “target” directory. Again, assuming all things went well, do
> cd target && ls
And you’ll see “classes” and “Potato.jar” So let’s run Potato!
> java -jar Potato.jar
You should be greeted with a friendly, if passive-aggressive, yet humerous message from your new Potato.

If *anything* went wrong, I suggest starting from the top of the first checklist, pinging Google. If you still can’t get it going, you may need to do some more research.

Here’s the TL;DR for those who just need a reminding of how easy (so easy, it’s forgettable) Java/Maven/Git is:

Get project url:
example: https://github.com/AeSix/Potato
Enter your working environment:
> cd ~/dev/git
Clone project to local system:
> git clone https://github.com/AeSix/Potato
Build with Maven:
> mvn clean install
Test the built jar:
> java -jar Potato/target/Potato.jar
Rejoice at the deliciously prepared Potato!

To update the local project files:
> cd ~/dev/git/Potato
> git pull
The git pull command has to be done from within the project’s local directory, otherwise it wouldn’t know which project to update.