301 Days

A year of gamedev experiments.

Day 58 - Huh.

| Comments

In which it becomes increasingly clear that our database snapshot and our code snapshot are not quite in sync.

APP_NAME

So we sit down and write a bunch of tests for APP_NAME. Even more than for APP_VERSION, because it shows up in more places:

features/config_file.featurelink
1
2
3
4
5
6
7
8
9
10
Scenario: APP_NAME reflected in the log
Scenario: APP_NAME reflected in the welcome message
Scenario: APP_NAME used when trying to ignore a staff member
Scenario: APP_NAME used in user list
Scenario: APP_NAME used in conference help
Scenario: APP_NAME reflected in the main menu
Scenario: APP_NAME reflected in the account menu
Scenario: APP_NAME reflected in the character menu
Scenario: APP_NAME reflected in welcome back message
Scenario: APP_NAME used in high score list

(In retrospect, I should probably go back and make the naming more consistent.)

Failure to ignore

After writing the support code for these, I still couldn’t get “APP_NAME used when trying to ignore a staff member” to pass. Instead of the expected chastisement:

DragonsSpine/Menus/Conference.cslink
580
581
582
if ((Globals.eImpLevel)DAL.DBPlayer.getPlayerField(ignoreID, "ImpLevel", ch.ImpLevel.GetType()) >= Globals.eImpLevel.GM) // cannot ignore staff member
{
    ch.WriteLine("You cannot ignore a " + DragonsSpineMain.APP_NAME + " staff member.", Protocol.TextType.Error);

…we get nothing. Looking in the logs for some insight:

1
6/25/2016 10:50:05 AM: {SystemFailure} DBPlayer.getPlayerTable(142, ImpLevel)  Field was not found in any player table.

ImpLevel? But in my database it’s actually impLevel, and everywhere else in the code it’s referred to as impLevel. Let’s check the scripts bundled with the server code:

DragonsSpine/SQL\ Scripts/Player.sqllink
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CREATE TABLE [Player]
(
  [PlayerID]     [int] IDENTITY NOT NULL PRIMARY KEY NONCLUSTERED ,
  [AccountID]        [int] NOT NULL REFERENCES Account(AccountID) ,
  [Account]      [nvarchar] (20) ,
  [protocol]     [nvarchar] (20) ,
  [Name]             [nvarchar] (255) ,
  [gender]       [int] NULL ,
  [Race]         [nvarchar] (20) NULL,
  [CharClass]        [nvarchar] (2) NULL,
  [CharClassFull]    [nvarchar] (15) NULL,
  [ClassID]      [int] NULL ,
  [Align]            [int] NULL ,
  [ConfRoom]     [int] NULL ,
  [ImpLevel]     [int] NULL ,

Oh, so it’s actually supposed to be ImpLevel. Messed around with SQL Server a bit to make sure I’m being properly case-insensitive, but that doesn’t help much when the server code is grabbing all fields and doing a string compare.

DragonsSpine/DAL/DBPlayer.cslink
39
40
41
42
foreach (DataColumn dc in dt.Columns)
{
    if (dc.ColumnName == field) { return tableNames[a]; }
}

So I change the capitalization of the field name and it still fails. Log says:

1
6/25/2016 11:21:55 PM: {SystemFailure} DBPlayer.getPlayerField(2, ImpLevel, DragonsSpine.Globals+eImpLevel) Unable to find DragonsSpine.Globals+eImpLevel in switch.

There’s no code to handle the type that ImpLevel is in the Character class. Not a DB issue, so it’s time to mark this case @bug and move on.

Hardcoding

Two more cases must be marked @bug, because the server code actually hardcodes the server name in the account and character menus.

DragonsSpine/Menus/Menu.cslink
85
ch.WriteLine("Dragon's Spine ("+DragonsSpineMain.APP_VERSION+") Character Menu");
DragonsSpine/Menus/Menu.cslink
102
ch.WriteLine("Dragon's Spine ("+DragonsSpineMain.APP_VERSION+") Account Menu");

Expect us?

config_file/features/config_file.featurelink
134
135
136
137
138
139
140
141
142
Scenario: APP_NAME used in high score list
  Given I use the "minimal" database as-is
 And I set "APP_NAME" in the config file to "Test HigSco"
 And the server executable is started
 And I allow time for the server to complete startup
 When I log on using a standard account
 And I enter the chat
 And I issue the high scores command
 Then I saw a high score list with application name "Test HigSco"

Doesn’t seem like it should be a problem, right? But the command /scores all is just returning usage info for the scores command. We know well enough to check the logs:

1
6/25/2016 4:36:21 AM: {SystemFailure} FAILURE: PC.getField(2, anonymous, False, Comments: )

anonymous? That’s not a field in the Player table. At least not in my Player table. I have a bad feeling about this…

DragonsSpine/SQL%20Scripts/Player.sqllink
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
CREATE TABLE [Player]
(
  [PlayerID]     [int] IDENTITY NOT NULL PRIMARY KEY NONCLUSTERED ,
  [AccountID]        [int] NOT NULL REFERENCES Account(AccountID) ,
  [Account]      [nvarchar] (20) ,
  [protocol]     [nvarchar] (20) ,
  [Name]             [nvarchar] (255) ,
  [gender]       [int] NULL ,
  [Race]         [nvarchar] (20) NULL,
  [CharClass]        [nvarchar] (2) NULL,
  [CharClassFull]    [nvarchar] (15) NULL,
  [ClassID]      [int] NULL ,
  [Align]            [int] NULL ,
  [ConfRoom]     [int] NULL ,
  [ImpLevel]     [int] NULL ,
  [ImpImmortal]  [bit] NOT NULL  DEFAULT (1) ,
  [ShowTitle]        [bit] NOT NULL  DEFAULT (0) ,
  [Echo]         [bit]   NOT NULL  DEFAULT (0) ,
  [Anonymous]        [bit] NOT NULL  DEFAULT (0) ,   

Time to take a serious look at how far we are from the expected DB schema. Tomorrow.


Useful Stuff

Selecting a SQL Server Collation

Part-time Game Development and Life Balance


Day 58 code - tests

Comments