Minecraft PC IP: play.cubecraft.net

Coding Behind the Cube #1 - Feelin' Lucky

Palombo

Lead Game Developer
Staff member
Developer
Nov 11, 2019
42
773
94
Hello CubeCrafters!

Welcome to the first edition of "Behind the Cube"! This is a different post than what you'd usually see here. These posts will be more geared around our backend development and how we as a development team deliver updates to you, the community. We'll be going more into detail about some of the internals of CubeCraft (which includes some sneak-peeks into our code!). Over the past few months, both our Java and Bedrock networks have seen a great amount of growth, and with that the amount of updates we've been able to deliver! We'll likely be going over some of the more recent updates in these posts, with this first one primarily being focused around the Lucky Islands game we recently released on our Bedrock network.


💻 About Our Bedrock Server Tech

So to start off, unlike what most other Bedrock servers do, we actually run a Java Edition-based server platform on our Bedrock network. And yes, you heard that right! When you join our Bedrock network, you're actually joining a server initially built for Minecraft: Java Edition. How this may be possible you ask?

On top of a bunch of modifications we've made to our fork of Spigot, CubeTap (yes, we run this on our Bedrock server too!), we actually have a fancy little program we developed in-house called Translator. As the name implies, it translates data from Minecraft: Bedrock Edition and converts it to something that Minecraft: Java Edition can understand and vice versa!

Here is one of the more simple translations Translator performs:

Java:
@Override
public void handle(ClientConnection client, AnimatePacket packet) {
    client.getJavaClient().getSession().send(AnimationMessage.builder()
            .hand(Hand.RIGHT)
            .build()
    );
}

Side note, we've recently adopted a free and open-source crossplay project called Geyser. We're planning to take parts of our tech we've developed here at CubeCraft and share it with the world!


🎮 Bedrock Game Creation

So, now that you know a bit more about our server tech, let's get a bit more into the actual games themselves! It's common for us to take games from our Java network and port them over to our Bedrock network without much of a hassle. Like stated above, the two networks are very similar, so we save a lot of time not having to completely recreate games when we want to bring them over from our Java network. Of course, we understand that the two games play very much differently, so we commonly have to tweak mechanics for games that we port over.

Additionally, there will almost always be features that our Bedrock network doesn't support that we will either have to remove or tweak support for. For example, when porting over Lucky Islands, we at the time didn't currently support colored potion particles on our Bedrock network, and many of the different loots did require the use of colored particles, so this was something our protocol team had to add support for.

On the other end, when porting over games to Bedrock, we also like to utilize some Bedrock-exclusive features such as custom entity models. Custom models on Bedrock allow us to add cool visual features to the game's experience without having to require the use of a custom resource pack. Every custom model is essentially a fake player that can then set a custom skin on.

A big difference between our Java and Bedrock Lucky Islands gamemode is that on Java, every lucky block is just a sponge that is then displayed as a lucky block from a custom resource pack. On Bedrock, every luck block is a custom model entity which gives us much more freedom by letting us have multiple custom skins in a single game, custom opening effects, and much more! Here is something we like to call "Lucky Steves," which is the beginning of what Lucky Islands looked like on Bedrock before we had any custom models created for them.

lucky-steves.png

QA said we couldn't release the game like this... you will be missed Steve.


🔧 The Development Process

At the beginning of Lucky Islands development, we wanted the ability to dynamically re-scale the lucky block when it was opened, so we could make a cool-looking opening effect. At the time though, we didn't have support for entity scaling. In this instance, our protocol team had to take over. Entity re-scaling is one of the many changes we've made to our Spigot fork which allow us to take advantage of features only available on Bedrock.

We already had support for this with the lobby NPCs, but it wasn't something we could use dynamically. Of course... we can't ask the protocol team to implement like this something and NOT have some fun with it! Here the demo of what they came up with:


Who said pigs couldn't fly?

For you geeks reading this, here's a code snippet showcasing how we tweak the lucky block size in the balloon lucky block effect:
Java:
new BukkitRunnable() {
    final Reptilian reptilian = luckyBlock.getReptilian();
    final Location lootLocation = reptilian.getLocation().clone().add(-0.5, 0.95, -0.5);
    final Location reptilianLocation = reptilian.getLocation().clone().add(0, 1.0, 0);
    final MutableLong ticks = new MutableLong(0L);
    final ParticleEffect particleEffect = new ParticleEffect(ParticleEffect.ParticleType.REDSTONE, 1, 0, 0);
    final Color color = luckyBlockOpenEffects.getLuckyBlockSkins().getColors().get(0) == null ?
            LuckyBlockSkins.REGULAR.getColors().get(0) : luckyBlockOpenEffects.getLuckyBlockSkins().getColors().get(0);

    @Override
    public void run() {
        reptilianLocation.setYaw(reptilianLocation.getYaw() + 2);
        reptilianLocation.setY(reptilianLocation.getY() + .20);
        reptilian.teleport(reptilianLocation);
        particleEffect.sendToLocation(reptilianLocation.clone().add(0, 0.20, 0));
        luckyBlockOpenEffects.getPreEffect().accept(luckyBlock);

        if (ticks.getValue().equals(0L)) {
            reptilian.setScale(0.80f);

            if (color != null) {
                particleEffect.setRGB((float) color.getRed() / 255, (float) color.getGreen() / 255, (float) color.getBlue() / 255);
            }
        } else if (ticks.getValue().equals(totalTicks)) {
            explosionParticleEffect.sendToLocation(reptilianLocation);
            luckyBlockOpenEffects.getPostEffect().accept(luckyBlock);
            luckyBlock.handleAfterEffect(player, lootLocation, loot);
            cancel();
            return;
        }

        ticks.add(1L);
    }
}.runTaskTimer(LuckyIslands.getInstance(),  1L, 1L);
Having support for entity scaling ventures out to a lot more than just to Lucky Islands and gives us a lot of room for some cool and creative games in the future.


📝 Configuring the Game

Configuring a game such as Lucky Islands could be very time consuming if we had to manually add every lucky block location for every map to a configuration file. To counter this, we had to decide if we wanted to replace sponge blocks with lucky blocks or use signs. We opted for having signs for two main reasons.

First, signs are much more efficient because they are easier to scan for in an arena because they are tile entities. Bukkit provides a method within the Chunk class to get all the tile entities in a chunk. Rather than looping through every block, we just need to check every tile entity. This drastically reduced the amount of processing we'd need to do due to the fact that we're only scanning through tile entities. Secondly, we were then able to store additional data in the NBT tags of those signs to then define which team those lucky blocks belong to. This allowed us to have per-team lucky block skins for players who have purchased the Lucky Blocks rank.

The Lucky Blocks rank on Bedrock gives players the ability to have custom lucky block skins as well as custom lucky block opening effects. A dynamic system had to be created to support the ability to have a different variation of an opening effect for each different skin that we support. For example, if you have the firework opening effect and the rainbow skin selected you will then have a rainbow explosion whereas if you have the tnt skin selected your explosion will be red, black, and white.

A big bump that we hit was that there was no way to allow players to select lucky block skins and opening effects when not inside the game. We didn't support loot skins menus at the time within the lobbies, so a brand new system had to be created for that. Boom - the skins menu system was created! We previously handled all of the skin loot menus (EggWars egg skins, BlockWars flag skins, etc.) within the games itself which wasn't very helpful to the developers or the players.

With the new skins menu system, we were able to get rid of much redundant code within our code base to now have an abstract SkinsMenu class that we can extend off of to allow for dynamic equippable loot anywhere on CubeCraft. We went from hundreds of lines of code to a single method call:
LootPluginAPI.getEquippableManager().getSkinsMenu(player, LootType.LUCKYBLOCK_SKIN);.
This allows for simple modifications of many equippable/skins menus without having to change code in multiple places. Long overdue and very helpful. If you were wondering how we can call these from our lobbies it's as simple as adding an action to our NPCs such as:
Code:
- action: CLICK
  results:
    - result: OPEN_SKINS_LOOT_MENU
      args:
        lootType: "LUCKYBLOCK_SKIN"
This just parses the LootType and runs the above method.


🔥 Q/A Testing

Every time we update a game, add something new or anything of those sorts, we do Q/A with the product team as well as staff testing. We like to get outside yet still a bit of internal input before we release anything to the community. With a staff team of over 100 people, we can get a good gist of how our players might feel about something new.

cam_slack.png

Doesn't look like @Camezonda got lucky this time

Even though we have that input, it doesn't always mean that we also catch something that the vast majority of our community won't like. One lesson we learned is that really listening to everything that the community is telling you is very important.

Surprisingly, a big complaint when Lucky Islands first came out on Bedrock was the lucky blocks opening instantly compared to something like breaking a sponge. To make players happy, we decided to knock 2 birds with 1 stone. We added a delay of 3/4s of a second between you clicking the lucky block and you receiving your loot. The first bird being now the time is closer to that of breaking a sponge. The other bird being we now had the ability to add cool effects that players could gain access to via a rank to show off to other players! Win-win!


This concludes the first edition of "Behind the Cube." We're planning to do more of these in the future to showcase a bit more of our inner workings and explain to you, the community, how we deliver content such as this and what problems or obstacles we may have ran in to. If anyone has any questions regarding anything mentioned in here, please feel free to reply below!

Written by:
 

Younisco

helping with all kinds of stuff
Staff member
Admin Team
May 13, 2014
7,745
15,931
634
18
London, England
This is a really interesting read - as someone with very little development knowledge, this entire blog post reads very fluidly. It's amazing to see how we are able to adapt to certain problems at a quick pace, so this is awesome to actually have some tangible way of proving that :D

Awesome work, @Redned & @Palombo ! 💙
 

Sergiio12

Member
Mar 4, 2019
1,087
1,953
189
16
España.
YES, just yes!!

I've been waiting for years to see something like this coming up. I'm really interested on the process behind the whole game and overall in game development so I've started by creating a /fly command haha

This is a really advanced coding though haha

Good work and keep doing things like this!
 

TheGamer2622

Member
Jan 12, 2020
10
10
4
20
London
Hello CubeCrafters!

Welcome to the first edition of "Behind the Cube"! This is a different post than what you'd usually see here. These posts will be more geared around our backend development and how we as a development team deliver updates to you, the community. We'll be going more into detail about some of the internals of CubeCraft (which includes some sneak-peeks into our code!). Over the past few months, both our Java and Bedrock networks have seen a great amount of growth, and with that the amount of updates we've been able to deliver! We'll likely be going over some of the more recent updates in these posts, with this first one primarily being focused around the Lucky Islands game we recently released on our Bedrock network.


💻 About Our Bedrock Server Tech

So to start off, unlike what most other Bedrock servers do, we actually run a Java Edition-based server platform on our Bedrock network. And yes, you heard that right! When you join our Bedrock network, you're actually joining a server initially built for Minecraft: Java Edition. How this may be possible you ask?

On top of a bunch of modifications we've made to our fork of Spigot, CubeTap (yes, we run this on our Bedrock server too!), we actually have a fancy little program we developed in-house called Translator. As the name implies, it translates data from Minecraft: Bedrock Edition and converts it to something that Minecraft: Java Edition can understand and vice versa!

Here is one of the more simple translations Translator performs:

Java:
@Override
public void handle(ClientConnection client, AnimatePacket packet) {
    client.getJavaClient().getSession().send(AnimationMessage.builder()
            .hand(Hand.RIGHT)
            .build()
    );
}

Side note, we've recently adopted a free and open-source crossplay project called Geyser. We're planning to take parts of our tech we've developed here at CubeCraft and share it with the world!


🎮 Bedrock Game Creation

So, now that you know a bit more about our server tech, let's get a bit more into the actual games themselves! It's common for us to take games from our Java network and port them over to our Bedrock network without much of a hassle. Like stated above, the two networks are very similar, so we save a lot of time not having to completely recreate games when we want to bring them over from our Java network. Of course, we understand that the two games play very much differently, so we commonly have to tweak mechanics for games that we port over.

Additionally, there will almost always be features that our Bedrock network doesn't support that we will either have to remove or tweak support for. For example, when porting over Lucky Islands, we at the time didn't currently support colored potion particles on our Bedrock network, and many of the different loots did require the use of colored particles, so this was something our protocol team had to add support for.

On the other end, when porting over games to Bedrock, we also like to utilize some Bedrock-exclusive features such as custom entity models. Custom models on Bedrock allow us to add cool visual features to the game's experience without having to require the use of a custom resource pack. Every custom model is essentially a fake player that can then set a custom skin on.

A big difference between our Java and Bedrock Lucky Islands gamemode is that on Java, every lucky block is just a sponge that is then displayed as a lucky block from a custom resource pack. On Bedrock, every luck block is a custom model entity which gives us much more freedom by letting us have multiple custom skins in a single game, custom opening effects, and much more! Here is something we like to call "Lucky Steves," which is the beginning of what Lucky Islands looked like on Bedrock before we had any custom models created for them.

View attachment 176972
QA said we couldn't release the game like this... you will be missed Steve.


🔧 The Development Process

At the beginning of Lucky Islands development, we wanted the ability to dynamically re-scale the lucky block when it was opened, so we could make a cool-looking opening effect. At the time though, we didn't have support for entity scaling. In this instance, our protocol team had to take over. Entity re-scaling is one of the many changes we've made to our Spigot fork which allow us to take advantage of features only available on Bedrock.

We already had support for this with the lobby NPCs, but it wasn't something we could use dynamically. Of course... we can't ask the protocol team to implement like this something and NOT have some fun with it! Here the demo of what they came up with:


Who said pigs couldn't fly?

For you geeks reading this, here's a code snippet showcasing how we tweak the lucky block size in the balloon lucky block effect:
Java:
new BukkitRunnable() {
    final Reptilian reptilian = luckyBlock.getReptilian();
    final Location lootLocation = reptilian.getLocation().clone().add(-0.5, 0.95, -0.5);
    final Location reptilianLocation = reptilian.getLocation().clone().add(0, 1.0, 0);
    final MutableLong ticks = new MutableLong(0L);
    final ParticleEffect particleEffect = new ParticleEffect(ParticleEffect.ParticleType.REDSTONE, 1, 0, 0);
    final Color color = luckyBlockOpenEffects.getLuckyBlockSkins().getColors().get(0) == null ?
            LuckyBlockSkins.REGULAR.getColors().get(0) : luckyBlockOpenEffects.getLuckyBlockSkins().getColors().get(0);

    @Override
    public void run() {
        reptilianLocation.setYaw(reptilianLocation.getYaw() + 2);
        reptilianLocation.setY(reptilianLocation.getY() + .20);
        reptilian.teleport(reptilianLocation);
        particleEffect.sendToLocation(reptilianLocation.clone().add(0, 0.20, 0));
        luckyBlockOpenEffects.getPreEffect().accept(luckyBlock);

        if (ticks.getValue().equals(0L)) {
            reptilian.setScale(0.80f);

            if (color != null) {
                particleEffect.setRGB((float) color.getRed() / 255, (float) color.getGreen() / 255, (float) color.getBlue() / 255);
            }
        } else if (ticks.getValue().equals(totalTicks)) {
            explosionParticleEffect.sendToLocation(reptilianLocation);
            luckyBlockOpenEffects.getPostEffect().accept(luckyBlock);
            luckyBlock.handleAfterEffect(player, lootLocation, loot);
            cancel();
            return;
        }

        ticks.add(1L);
    }
}.runTaskTimer(LuckyIslands.getInstance(),  1L, 1L);
Having support for entity scaling ventures out to a lot more than just to Lucky Islands and gives us a lot of room for some cool and creative games in the future.


📝 Configuring the Game

Configuring a game such as Lucky Islands could be very time consuming if we had to manually add every lucky block location for every map to a configuration file. To counter this, we had to decide if we wanted to replace sponge blocks with lucky blocks or use signs. We opted for having signs for two main reasons.

First, signs are much more efficient because they are easier to scan for in an arena because they are tile entities. Bukkit provides a method within the Chunk class to get all the tile entities in a chunk. Rather than looping through every block, we just need to check every tile entity. This drastically reduced the amount of processing we'd need to do due to the fact that we're only scanning through tile entities. Secondly, we were then able to store additional data in the NBT tags of those signs to then define which team those lucky blocks belong to. This allowed us to have per-team lucky block skins for players who have purchased the Lucky Blocks rank.

The Lucky Blocks rank on Bedrock gives players the ability to have custom lucky block skins as well as custom lucky block opening effects. A dynamic system had to be created to support the ability to have a different variation of an opening effect for each different skin that we support. For example, if you have the firework opening effect and the rainbow skin selected you will then have a rainbow explosion whereas if you have the tnt skin selected your explosion will be red, black, and white.

A big bump that we hit was that there was no way to allow players to select lucky block skins and opening effects when not inside the game. We didn't support loot skins menus at the time within the lobbies, so a brand new system had to be created for that. Boom - the skins menu system was created! We previously handled all of the skin loot menus (EggWars egg skins, BlockWars flag skins, etc.) within the games itself which wasn't very helpful to the developers or the players.

With the new skins menu system, we were able to get rid of much redundant code within our code base to now have an abstract SkinsMenu class that we can extend off of to allow for dynamic equippable loot anywhere on CubeCraft. We went from hundreds of lines of code to a single method call:
LootPluginAPI.getEquippableManager().getSkinsMenu(player, LootType.LUCKYBLOCK_SKIN);.
This allows for simple modifications of many equippable/skins menus without having to change code in multiple places. Long overdue and very helpful. If you were wondering how we can call these from our lobbies it's as simple as adding an action to our NPCs such as:
Code:
- action: CLICK
  results:
    - result: OPEN_SKINS_LOOT_MENU
      args:
        lootType: "LUCKYBLOCK_SKIN"
This just parses the LootType and runs the above method.


🔥 Q/A Testing

Every time we update a game, add something new or anything of those sorts, we do Q/A with the product team as well as staff testing. We like to get outside yet still a bit of internal input before we release anything to the community. With a staff team of over 100 people, we can get a good gist of how our players might feel about something new.

View attachment 176973
Doesn't look like @Camezonda got lucky this time

Even though we have that input, it doesn't always mean that we also catch something that the vast majority of our community won't like. One lesson we learned is that really listening to everything that the community is telling you is very important.

Surprisingly, a big complaint when Lucky Islands first came out on Bedrock was the lucky blocks opening instantly compared to something like breaking a sponge. To make players happy, we decided to knock 2 birds with 1 stone. We added a delay of 3/4s of a second between you clicking the lucky block and you receiving your loot. The first bird being now the time is closer to that of breaking a sponge. The other bird being we now had the ability to add cool effects that players could gain access to via a rank to show off to other players! Win-win!


This concludes the first edition of "Behind the Cube." We're planning to do more of these in the future to showcase a bit more of our inner workings and explain to you, the community, how we deliver content such as this and what problems or obstacles we may have ran in to. If anyone has any questions regarding anything mentioned in here, please feel free to reply below!

Written by:
You obviously have a brain I mean I can't even do simple phyton :v
 

Nimaex

Infrastructure Apprentice
Staff member
Developer
Aug 4, 2020
14
67
23
Liverpool
Could this also port Forge Mods to Bedrock edition or is that impossible
Forge mods require you to install them clientside, so we can't port them directly to bedrock without a bedrock version of the mod (the Bedrock client is very different to the Java one). There is also the fact that forge sends custom packets, block types etc from the server to the client (and vice versa) which Translator wouldn't understand.
 
Discord
Members Online

Team Online

Latest posts

Latest profile posts

the antihack is disabled? I've been playing for more than 3 hours and hackers are everywhere
Thanks for 270 followers, everyone! <3
Spooky BrilliantBenji wrote on The Cube Craft Times's profile.
We are pleased to announce our partnership with CCGN. You will hear more about it later.
Khxliee_ wrote on Spook1ster's profile.
Thanks for following khzmut :')
Top Bottom