Hytale Bedwars Plugin banner

Hytale Bedwars Plugin

16 devlogs
85h 7m 20s

Porting Minecraft minigame Bedwars to Hytale (the new voxel rpg game by Hypixel authors).

This project uses AI

AI was only used to help me better understand how to use async in Kotlin. All of the remaining code was written purely by hand.

Demo Repository

Loading README...

Szczurek

Shipped this project!

Hytale Bedwars Plugin is shipped!

Wohoo!
I made a Bedwars plugin for Hytale, the new voxel rpg game. Or at least half of it, since I didn’t manage to finish it. It was fun, and I’m looking forward to continue the development.

What was hard

Definitely debugging weird issues coming from quirks of Hytale being in alpha state, and having to fight some of it’s limitations. The fact that there isn’t much documentation also makes thing hard, because you have to figure out a lot of stuff by trial and error.

What I’m proud of

Definitely the shop UI - I really like how it turned out, despite being made just in the last two days. It uses the UI system to it’s potential, conveing more then a Minecraft chest GUI, while still being quite compact.
I’m also happy that many things in the project are data driven and can be changed from the asset edit. This even includes things like teams. Ever wanted a Teal or Violet team? Make it.

What I’m not proud of

  • That I didn’t manage to implement the gameplay loop during Flavortown
  • That it’s ten until 3am as I’m shipping this, 4 hours before the deadline.
Szczurek

The last sprint

The end of Flavortown is upon us, and it’s closer than you think, don’t look!
looks
It’s literally 7 hours till end, and it is 12pm in my timezone.
SCREAMS
However I managed to do some quite nice changes in the last two days, so let’s quickly check them out.
Most importantly I managed to finish (or at least make quite functional) the item shop GUI.
Thanks to the Hytale’s custom UI system it looks much better to its Minecraft counterpart.
I wanted to keep the familiar simplicity of chest guis, while conveying more information.
So I decided on a simple widget for each item composed of it’s price, the resource it costs as a smaller 32x32 slot, and a bigger 64x64 slot displaying the item you are buying. I also made the border of the price icon glow green if you can afford the item to help quickly identify what you can and cannot buy. Additionally when you buy something you get a pickup notification in the corner. Similarly you get a notification if you try to buy an item you cannot afford. The best would be displaying the player’s inventory under the shop, but Hytale doesn’t give you that ability yet, so we must do with what we have.
I also added a shopkeeper npc that opens the shop, which is just a slightly modified klops merchant from vanilla Hytale. Despite that I had to make 3 new boilerplate’y classes to open the shop gui from an npc.
Finally I quite a critical bug concerning map loading. The game sometimes failed to load, because sync chunk loading took too long. I had to quickly replace it with async loading.
With that fixed, that’s it for Flavortown, so thank you for taking the road with me, I hope you enjoyed it!

Attachment
Attachment
0
Szczurek

How hard TabNavigation could be?

“So, 7,5 hours passed, what did you do?”
“TabNavigation”
“what? like you implemented some advanced ui navigation system?”
“TabNavigation. I implemented TabNavigation. An empty page which has tabs at the top you can switch”
“WAT?”

No, I did more, but from the time counted here, getting the built-in into Hytale TabNavigation ui component literally took 5 or 6 hours.
Why you may ask?
Well, the tabs are supposed to be set up dynamically from the code based on json, and as it turns out there is no api in Hytale to do that. Hytale is mostly an undocumented project, which means that you discover how to do things by reading existing code of the game, and trial and error. I spent hours trying out different functions and parameters just to add few tabs to the TabNavigationui component provided by the game.<br> Nothing worked, which drained my motivation, and the real life got busy which made me take a break from the project.<br> Fortunetely, when I came back few weeks later, I found that some folks in the HytaleModding discord figured out a workaround, which involved calling a private method via Java reflection, and manually assembling the json to be sent to the client. (For context ui is controlled server side in Hytale, and changes to it are sent to the client as a list of commands (like add, append, delete) in json).<br> After understanding how it works, I implemented my own solution, which instead of messing with json used java reflection to register a custom data class which I namedNavigationTabrepresenting the tab in the api. That made it possible to call the standardsetmethod with aList`, which were then serialized properly by the game and sent to the client, making the tabs finally work.

Icons have issues too

After that I encountered an another problem. I was hoping to use the textures of items and the game as icons as it is commonly done in Minecraft, but it seems that Hytale is unable to use any textures placed outside of the Common/UI folder in an asset pack for UI, and the icons are located in Common/Icons :(
So I will probably have to use some custom textures, or copy them over to the Common/UI directory.

Other changes

One more thing worth noting off is that I also refactored the code to make it compile on the latest Hytale pre-releases, which removed all Vector types like Vector3d and Vector3f (classes keeping x,y,z values, used for positions and rotations of everything), and replaced them with their counterparts from JOML (Java OpenGL Math Library).
That’s it for today, bye!

Attachment
0
Szczurek

Game init and the basics

The countdown has got sounds, and now something actually happens after it.
The players get teleported to the islands. This also means a team assigning algorthm is in place. It is not perfect, but it should work pretty well, and it has it already accounted for an integration with a party system.
Any unnecesary marker entities get removed and the generators start spawning resources. They also got a title that displays when an item will spawn (for diamonds/emeralds), and the items now don’t stack, so you can clearly see when there is many of them.
Blocks are now protected from destruction, though for now it affects everything including the bed and anything the player places. This will be fixed once I will have other systems required for it in place.
I also have a shopkeepers system work in progress, but time is running out and I didn’t manage to finish them, so they will be in the next blogpost.

Attachment
Attachment
0
Szczurek

Starting the game

After adding a fix to make sure chunks are loaded during validation map editing is mostly finished.
This means we can start working on the actual gameplay.
So, after a bunch of coding, we got an API (and command to invoke it for testing) that creates a new bedwars game, by creating a copy of a map, finding all queue spawnpoints and teleporting players to one of them. The world is automatically managed, and removed after all players leave (because no one wanted to play or the game ended). We also got ourselves a countdown that… counts down to the game start.

Attachment
0
Szczurek

Map editing progress

Map editing has got an enitre validation system, which ensures that map setup gets completed, before it can be played.
It makes sure that there are at least two different teams placed on the map, and a place for players waiting for game to start is selected. Those warnings can be checked with new /bw map validate command. The player is also warned when leaving the map if it isn’t ready to be played.

A Snapper Tool has also been added, which can be used to snap entities to block grid centers and edges, allowing for more precise placement of spawnpoints and generators.

The marker entities for spawnpoints have also been added, and all of them got new textures.

Attachment
0
Szczurek

Async and assets

I added two new assets: BedwarsTeam and BedwarsMap
The first one defines bedwars teams, letting you assign a colour and a name to each of them.
The second one stores neccesary metadata about bedwars maps, such as the amount of teams it can support. It is automatically created when you create a bedwars map with a command. Getting this to work took a lot of struggle and my time. For some reason trying to save the asset to a file was locking up the entire server.
After a lot of debugging, I realized hytalemodding.dev was wrong, and made me think my code is executing async, while it was executing on the world thread (which caused the problem). I sent a PR to them to correct that, and adjusted my code, which solved the problem. I in the end I heavily reworte the involved code. First I removed the use of CompletableFutures, because they annoyed me. Then I made it use Kotlin coroutines, after learning how to use them, which finally made the code more bearable. I also changed the error handling to use a custom exception to contain a formatted, translatable message.
While not very much productive for the features, this session did a bunch of good things for the code, which should accelerate things in the future.

PS: I made the /bw map list command work by using the new map asset

Attachment
Attachment
0
Szczurek

Bedwars map editing and exit

You can now exit the edited bedwars map, and then return it. This took longer then expected to implement due to some issues with world lifecycle management and teleportation. The code responsible for managing maps also got some better organization.

0
Szczurek

Why don’t you write it in Kotlin?

A friend said.
I agreed.
I hope he was right.

Kotlin is pretty weird in my opinion, like Java + Python, but it also had to do a bunch of things in its own way, without s clear reason why. But it has null safety without having to write @Nonnull everywhere, and dunks on java getters and setters which are pure boilerplate (and were starting to annoy me). That + a nudge from a friend is enough for me to go for it.
So yeah, I refactored the project into Kotlin and I hope it pays off in the long term.

Note that I deleted some unused files, so the added to removed ratio is off, I didn’t save whole 250 lines just by switching to Kotlin.

Attachment
0
Szczurek

Empty world creation

Next up in the works is map management, starting with the ability to create a new empty world. where you will be able to build your bedwars map.

0
Szczurek

Did you drop a generator?

Or 10 of them?
I fixed the generators disappearing after server restart.
The culprit of it was NetworkId component, which assigns an unique integer id to every entity, and lets the server communicate to the client which entity it is talking about. The problem? They are manual! You need to assign a NetworkId when you spawn an entity (which I did), but you also need to assign one, once the server loads the entity from storage!
After I added an ECS system to do so, a bunch of generators, which were saved, just not visible, showed up.

Attachment
0
Szczurek

Configurable generators

The work on item generators continues, and I’m baffled to see that this devlog is representing 9 hours of coding - time passes quickly.
There is however a nice list of changes:

  • Generators have been moved from json to code. This means they are no longer running away (see previous devlog). However a new problem emrged - the don’t get saved on server shutdown for some reason, and are gone after restart. I spent over an hour debugging this already, with no success so far.
  • The generator is now spawned with /bedwars spawn generator command, instead of using the entity tool, which is a side effect of moving generators to code.
  • Custom Hytale asset has been created, which allows for configuring the generators (what items and how often they drop) using the built-in Hytale Asset Editor. The asset also supports generator upgrades, so multiple level can be configured.
  • A custom UI and interaction has been made, which allows the user to select which asset to use for the generator, and to activate it for testing.
  • The generator stores a reference (id) of the configuration asset it is using, so it will be able to persist that data in map templates.
0
Szczurek

Is it a bird? Is it a plane? No, it’s an item generator!

And it is flying away!

But it is working, dropping items as it should.
The reason it is flying away is that entities made with json need a movement type, and by default the “Fly” type keeps going forward it seems. I’ll find a fix for it.

On the recording items are also spawning in slightly incorrect location, which is already fixed.

1

Comments

dapsvi.universe
dapsvi.universe 4 months ago

thats so sick !

Szczurek

Bedwars command is up

The setup is done, so the development can finally take off, and the devlogs will be actually interesting and more frequent now.
We are starting with a /bedwars command fresh from the oven. The command will be used to manage bedwars maps, and to start a game without using the API.

I have not explored Hytale modding much yet, but I do love it already.
I just registered the commands structure, and look what I get for free - an entire help menu for my command that is automatically generated.

Attachment
Attachment
0
Szczurek

Setting up Hytale modding - the ever changing landscape

So, how long does it take to setup the dependencies and run something that released 2 days ago in a dev environment?
5min? 10min? 15min?

Yes, it is 15 minutes, unless you are also running your IDE inside flatpak, using the kotlin build scripts for the first time, and trying to follow two different templates at once, which happens to be me.
In that case it takes 2 hours.
And then, the next day I find myself deleting all the changes I made, because a gradle plugin got released in the meantime, which does the same job better.

The plugin had few little things missing, so I spent some time working on it, made a PR, and talked a little with the author.
Today I also made another PR, which instantly got closed, becaused I and the author coded the exact same feature in the exact same time. 😆

With all the changes made the gradle plugin has all the features it needs, and thus I present to you:
The smallest, cleanest build.gradle.kts file you have ever seen

Attachment
0
Szczurek

Preparing for Hytale

As I am writing this, we are 2 hours apart from Hytale release. This means that the main work will soon be able to take off.

In the time from project start to now, I have made the BedwarsTracker tool (which is also available to try out on github btw.), wrote the code for an item generator, and most importantly spent much time experimenting with json, to get a good hang of what will work well as Hytale Assets for configuring the plugin.
For example teams will be data driven, meaning you can create as many (or few) as you want.

Attachment
0
Szczurek

Tracking Hypixel Bedwars generators

I’m creating an exact replica of the Hypixel Bedwars, which means I need to know how fast iron and gold spawns in generators.

I tried to count this by hand but it was very cumbersome and error prone. I also had to sit in the forge which meant so I couldn’t defend the bed. So I created a Minecraft mod, that will do this for me.

Writing the mod

First I tried tracking items being added to the player’s hotbar, and it worked, but I still had to sit in the generator.
So with second attempt I started tracking item entity spawns, which didn’t rely on the player. After implementing that I could play as long as I didn’t go too far away from the forge, because then the items would not spawn client side. The server spawns them back after coming back close, which I also had to account for, to not have duplicated data.

Analyzing the data

The mod generates a CSV file with raw data, that needs to be analyzed. So I
wrote a python script which:

  • Removes some noise, by discarding entries that have a very big delay between
    them.
  • Merges item spawns that occured in short period of time (because Hypixel spawns each item individually) into one spawn with correct count.
  • Groups spawns using HDBSCAN algorithm with hyperparameters tuned for each item type to find different forge speeds (because the speed changes after 30s, and when you upgrade the forge).
  • Calculates the average delay for each group and prints it in the console.
  • Plots the delay against time.

A discovery

Seeing a chart lead to an interesting discovery:
Did you know that generators are at least 2x faster during the first 30 seconds of the game? I certainly didn’t.

The result

In the end, this yields us the attached charts.
Note: As you can see the algorithm stops working very well after you upgrade the forge, because the data is a bit weird. I might spend some time later to fix that, but for now this is enough.

Attachment
Attachment
Attachment
Attachment
Attachment
Attachment
0