Minecraft PC IP: play.cubecraft.net

30q5

Member
Sep 26, 2020
13
12
9
21
Sweden
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:
This was very interesting to read. Upload more of how it works! :)

The most interesting thing for me is how the join menus for all the games in the lobby works. I would really like to see something of that in the next post too :))
 

Katsia Stray

Well-Known Member
May 18, 2020
742
931
124
Jupiter
www.youtube.com
Pronouns
He/She/They
That is so nice to read! I'd love a storytime on how some gamemodes were made tbh 😂

(Eg how they came up with some games, scrapped ideas, anything else that was meant to be implemented but didnt, old models etc)
 

SoSander

Member
Sep 12, 2020
11
11
4
18
WoW, I really liked this, I hope to see more of this in the future! great work devs!
 

MixeCube

Member
Aug 12, 2021
2
0
17
18
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:
Cool :0
 

BurntCrown8876

Well-Known Member
Nov 9, 2021
332
911
114
My Cat's Basket
allout.org
Pronouns
He/Him
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:
Wow, I've always wanted to know how it works... Careful a rival server doesn't pinch it! 😂
 

fireball33321

Member
Nov 27, 2021
1
3
4
17
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:
Egg
 
Members Online

Team online

Latest profile posts

jamesthesignificant wrote on Hqteful's profile.
Do you like the beatles- if yes what's ur favourite song by them
jamesthesignificant wrote on S4nne's profile.
Hi! I'm new, and I don't really understand necroposting. There is an option to tick that says 'I understand that this post is 3 months old and would still like to reply', should we just never tick that? If so, what is its purpouse?
UncleSpect wrote on Ryaan's profile.
Happy birthday!
Top Bottom