FFXIV 1.0 Classic Server Dev Blog

Binding to the Database

The server is become a bit less hardcoded! I've been spending the weekend writing out sql queries and designing the database to store all the character information a player can have. I *think* I have everything covered, now it's just a matter of writing the utility functions I need to load/save certain data, as well as write the proper property init/set functions.

Here is what the db looks like so far:


Not all of these tables are being used currently. However I have most of the login stuff completed and no longer rely on the packet files to load the player (still need it to load the other npc objects)! Most of the data is loaded in as well including position, job/level data, journal, player profile, and timers. It's not 100% done because I am having trouble setting the command properties (hotbar) and the general parameters (stats). Crashes the game.

Here is the journal being driven by the DB rather than a hardcode:


The Event System (Formerly called the Script System)

So I didn't get any luck finding where the path companion is set, and instead began working on a more complex feature: the event system (which I used to called the script system).

I've got my head around how it works which unlocks a lot of possibilities with the game. As I've mentioned before, every actor has a script bound to it as it's created. This basically instantiates a new object in the Lua engine as the class you are binding to it. For example, if you want an NPC to have access to the PopulaceLinkshellManager (LS Person) script, you instantiate it as a PopulaceLinkshellManager object in packet 0xCC. Then this actor is initialized according to it's lua script (IE: a Retainer will have it's nameplate purple), and the server can call it's functions. Here is an example:

I've spawned Emoni; the linkshell manager that stood in the Carline Canopy (aka Adventurer's Guild). Her Lua object was instantiated from the PopulaceLinkshellManager class, so any function I send to her has to be part of that script.


When I talk to her, the client will send packet 0x12D to start the event. Given is the actor id involved, something I call an "eventStarter" (not sure what it actually related to) which for NPCs is "talkDefault", some fields I don't know yet, and a bunch of Lua parameters.


In response, the server sends 0x130, telling what function to fire as well as the original "eventStarter". Lua parameters are also given. In the LinkshellManager script is a bunch of functions labeled "talkEvent1", "talkEvent2", etc. TalkEvent1 and 2 take a single boolean, if false the NPC acts like you never saw a LS, if true the opposite. I skipped "talkEvent1" since it's just an intro speech, and instead fired "talkEvent2" with the boolean set to false.


After going through the LS creation process, the client sends a 0x12E packet, the "EventUpdate" packet. This basically means the function has returned with some parameters and the client now waits for either another function to fire, or the "EndEvent" packet 0x131. Here you can see the script returned the chosen name and crest the player selected.



My plan is to move all this processing into lua scripts so that new handlers can be added and modified with ease. After this is built and fleshed out, a LOT of the game will be easier to implement. NPCs are not the only thing that uses this: 90% of commands in the game fire off a start event packet, though a lot don't go through the whole update/end event portion. Stuff that send 0x12D include emotes, battle actions (ws/spells), basic functions like check/trade/invite/kick/etc, and some menus.

Higher res pictures here: http://imgur.com/a/YrvRx

Christmas Update

I've been a bit busy over the last couple of weeks with family and IRL stuff, so I haven't done as much work on the server as I wanted to. Still I've got a bunch of things completed...

I went through the login sequence line by line; comparing the new login packets I received with what my server was doing programatically. I reordered a bunch of packets and fixed a few bugged ones. In the end I was able to stabilize login and the game no longer crashes when you try to login a second time.

A bunch of known packets relating to actor initialization were implemented.

I found a few more packets: The single status version of the "Set Status" packet. The original one I had was for actor creation... if you walked in range of a player full of buffs/debuffs you'd use 179 to set everything in one go (up to 20 statuses). 177 however sets one at a time; used when a status is applied or removed. Next I found 19F, one of the last 19X packets. This sets the "AchievementRate" (as the game calls it) for an achievement. Basically, how many ___ until you finish (IE: Kills), as well as flags for achievements that required you to do X different things (IE: Kill 7 unique NMs). Finally I implemented the list packets in code. These are used to setup the retainer and party lists.

After finding 19F, achievements are 100% complete.


I am currently looking into finding where to set the Path Companion. A bunch of cutscenes crash the game due to no companion data is set.

Linkshell and Retainer progress... plus more!

Thanks to those sniffed packets I've documented many more opcodes and figured out more or less how linkshells and retainers work (the lists). Both of them (plus parties) use a bunch of "list" packets to set their data. These packets are complex and I am still figuring them out, however I got the basics down. Linkshells and Retainers have their own parameter packet like actors do, but these bind to some ID rather than an certain actor. Anyway, here are some screenshots:

Here are some test linkshells... with the third one active.


Here I loaded all the players in the LS (this is from the original test LS). I can change the ranks and online/offline state of each player.


Finally here is the retainer list with their states and position active. This was visible in Seventh Umbral, but the retainer states weren't set.



New sniffed packets and started to look into Linkshells

Another developer came into contact with me and dropped a beautiful early Christmas gift in my lap: A whole slew of sniffed packets dating from alpha all the way to 1.23b. He was working on a private server at the time the game was alive and had captured a lot of data. Unlike Seventh's Umbral sniffs, his character had completed most or all of the content so I have access to packets that a endgame player would see. You'll be seeing a lot more more progress as I have now three to four different characters to compare against and see what SE was doing.


I started by finishing off the last few unknown 0x1A_ and 0x19 packets I was looking for.

0x199: Set Grand Company packet. This sets your current allegiance and rank in all three GCs.

0x1A1: Set Has Goobbue Mount packet. This makes the icon in the bottom right appear.


I also found some of the linkshell packets and have been able to make the list appear, set the current active LS, and fill the member list!

Decoded the animation IDs

I didn't do too much packet decoding today, instead figuring out how the animation IDs that battle packet references worked. 90% of the time with FFXIV, if you see a long ID it's probably made up of smaller IDs. In the case of the animation ID its 3 bytes of particle effect, 3 bytes of animation, and a byte for category. These categories correlate to the folders under the client/vfx folder in the game path.

From what I found:

MGK: 01
SYS: 02
LIB: 046
ITM: 05-09
GL2?: 0B
GL1: 0C
CFT: 10
PIC: 14
WSC: 12

The animation IDs seem to match the particle effects so more often than not no animation will play but the particle effect will. I did figure out to look under the act folder in ever PC classes' folder for the animation IDs. Anyway here is a video of chaos thrust:

Newer posts → Home ← Older posts