301 Days (redux)

Another metric leap year of gamedev experiments and such

Day 58 - Huh.

Jun 25, 2016 - 4 minute read - OldDaysseitan-spin

Super Mario Crossover

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.feature GitLab
 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.cs GitLab
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:

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.sql GitLab
 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.cs GitLab
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:

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.cs GitLab
1
ch.WriteLine("Dragon's Spine ("+DragonsSpineMain.APP_VERSION+") Character Menu");
DragonsSpine/Menus/Menu.cs GitLab
1
ch.WriteLine("Dragon's Spine ("+DragonsSpineMain.APP_VERSION+") Account Menu");

Expect us?

config_file/features/config_file.feature GitLab
1
2
3
4
5
6
7
8
9
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:

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.sql GitLab
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
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


More to come

Day 58 code - tests