Published on

Devlog #42 - 800+ Club

We just crossed 800+ total members!

Welcome to all the free and paid tier members!

Battle Pass #1 has been delayed one more week to January 26, 2024. You must be a Gamer tier or above patron on January 26, 2024 to receive the Winter Battle Pass item in your in-game mail.

For issues related to Patreon please DM me directly on Patreon.
For bugs in the game or website please post to #bugs on Discord.

https://discord.gg/fantasyonline2

I've started investigating moving all servers from https://overcast.smartfoxserver.com/ to https://aws.amazon.com/. Overcast uses AWS under the hood but makes creation of MySQL and Smartfoxserver cloud machines very easy. The first server we'll be moving is the MySQL server.

Currently FO2's MySQL server is a micro. AWS likes to generalize names of servers with micro, small, medium, large etc to hide how many virtual CPUs and RAM you get. Overcast does this as well.

Here is Overcast's current cost per month for a MySQL instance.

A.Micro ____ 22.21 €/month

A.Small ____ 41.19 €/month

A.Medium ____ 79.14 €/month

So we currently have a micro which is:

A.Micro

Volume Size 20 GB

Incl. Data Transfer 30 GB/month

FO2 doesn't do a whole lot of reading and writing to MySQL currently. When the game starts/reboots it reads all the definitions in. When a player logsin/logsout it read/writes the player data. Also, our database is only about 160MB right now. So micro is still big enough for Alpha Phase 2. So let's see how much a micro costs over at AWS.

Amazon has many services under the AWS roof. Amazon RDS is where the relational databases are. So with that in mind I filled out a MySQL Amazon RDS creation form with all the properties that our current micro server has and voila:

DB instance

12.41 USD

Storage

2.30 USD

Total

14.71 USD

So there we go, if we convert Euros to Dollars the Overcast micro costs 24.34amonthandtheAmazonversionofthesamethingcosts24.34 a month and the Amazon version of the same thing costs 14.71 a month. That's a huge savings! Oh but actually if you buy a year from Overcast they discount it 30% so it's actually $17.04 a month which is still more. Also, the first 12 months of a micro machine at AWS are free. Yeah, I think it's worth it to migrate to AWS from Overcast, at least for MySQL.

The only problem is Amazon RDS MySQL instances don't have any frontend. Overcast supplies PhpMyAdmin to easily administer their database instances. I guess I could create an AWS EC2 micro for the test server and install PhpMyAdmin along side it. Yeah, that sounds like a good plan!

So while AWS MySQL looks like a small savings, we still need to investigate AWS EC2 instances to see how much the game servers will cost. Then there's also the redis instances we'll need for fast read/write of player data. AWS is looking very promising and I think it will be doable to migrate things over the next couple of months. Next week we'll look at AWS EC2 instances and look into how many virtual cpu cores we can get for a reasonable price. We're going to need quite a few cores to handle all the connections from F2P players in the fall.

And now back we go to Battle Pass work. Next up we need to load the MySQL tables into Java classes on the server. BattlePassDefinition and BattlePassTierDefinition are the Java classes that now take data from the MySQL tables BattlePassDefinitions and BattlePassTierDefinitions. These definitions only need to be sent to the client when the player has an active Battle Pass.

So what we actually need now is a server message handler to send active Battle Passes to the client. The message handler needs to select all active Battle Passes from the BattlePassesActive MySQL table, then grab all the related definitions for the Battle Pass and its contents, and then send it to the client. I'm going to go ahead and insert an active Battle Pass into the MySQL table manually for now, but we'll need to implement the Battle Pass consumable item when we're all done here. Here's what that looks like when exported from PhpMyAdmin.

CREATE TABLE BattlePassesActive (

Id int(10) UNSIGNED NOT NULL,

BattlePassId int(10) UNSIGNED NOT NULL,

AccountId varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL,

StartTime datetime NOT NULL DEFAULT CURRENT_TIMESTAMP

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO BattlePassesActive (Id, BattlePassId, AccountId, StartTime) VALUES

(1, 1, '8074839e-7b60-451f-97ff-61bacc4d2112', '2024-01-07 01:20:50');

So now that the first active Battle Pass is in the database, our server code can select it with the following.

"SELECT * FROM BattlePassesActive WHERE AccountId=?"

Once we have that row's data in Java we can pull it apart and pair it with all the necessary definitions that were loaded into memory on server start. If a tier has an item reward, we need to include the item definition. If a tier has a quest, we need to include a quest definition, and so on and so forth.

When a player logs in, their data is loaded and sent to the client over time. Their inventory, then zone data, then other players, then mail, and now we'll add active battle passes to the end of that chain. It's split up like this to avoid heavy server load on login. So we now request the active Battle Passes after the player join message is received and then we receive all that juicy Battle Pass data as a result.

The active Battle Pass data is parsed into the TypeScript classes below.

interface IBattlePassTierDefinition

t: number;

rt: number;

r: number;

j?: string;

class BattlePassTierDefinition

constructor(battlePassTierData: IBattlePassTierDefinition)

interface IBattlePassDefinition

bptd: IBattlePassTierDefinition[];

class BattlePassDefinition

readonly battlePassTierDefinitions: ReadonlyArray<BattlePassTierDefinition>;

constructor(battlePassData: IBattlePassDefinition)

this.battlePassTierDefinitions = battlePassData.bptd.map(battlePassTierData => new BattlePassTierDefinition(battlePassTierData));

interface IBattlePassActive

id: number;

bpd: string;

class BattlePassActive

readonly id: number;

readonly battlePassDefinition: BattlePassDefinition;

constructor(battlePassActiveData: IBattlePassActive)

this.id = battlePassActiveData.id;

this.battlePassDefinition = new BattlePassDefinition(JSON.parse(battlePassActiveData.bpd));

On the server side we convert MySQL into Java Objects on game server startup which are then converted into JSON strings to put in packets to send out into the internets. We send those JSON strings to the client where they're parsed into TypeScript Objects. We use interfaces on the JSON data for type safety and then convert that data into a usable class. As you can see these classes are not done yet but you get the idea. The Java Objects have short names to make the JSON packets sent to the client smaller. We use descriptive names on the client to make it more readable as these classes won't ever been turned back into strings and sent over the interwebs. I also don't export these classes as they are only used in one file which is BattlePassGUIWindow.ts.

So there we go, now we just need to display the Battle Passes in the Battle Window on the client! We'll also need a claim reward message handler and a Battle Pass item consumable item handler, along with a trigger that ends the Battle Pass if time runs out. We're nearly there.

This is a preview of one of the sets in the Battle Pass! It looks so good!

We've had 3 patches since the start of 2024 which have included a bunch of new drops, quests, bug fixes, and a new Buccaneer Box set!

Patch Notes #23 - Swamp Grotto Mobs & Drops

Patch Notes #24 - Mirabella Grotto

Patch Notes #25 - Arrr

Work has started on Mirabella Cove and that has led us to actually having a world map! Look at that! We're going to need a zone below MC to complete the square of 4 zones. Cave of Some Return is under Crab Coast, Swamp Grotto is under Mirabella Cove, so maybe Cave of Despair will go under Noob Island? We'll see.

Mirabella Cove is live for mods but as you can see I still need to update it to new the tile set.

Huge thanks to Perseus for his continued hard work on great looking art like the Buccaneer Box pictured above.

If you haven't seen it already here is the roadmap for the next 6 months Alpha Phase 2 Roadmap.

Don't forget to vote on the next box set What should the next box set be?.

And vote on the number of skill hot bars How many skill hot bars?.

In the upcoming week we'll continue to work on code and content for Battle Pass #1 which will 100% be released on January 26, 2024. I'll also continue working on AWS setup and migration, bug fixes, Swamp Grotto quests and drops, and more.

See you next patch notes!

Have Fun & Keep Gaming!