301 Days

A year of gamedev experiments.

Day 49 - Minimalism 3: Small Town Blues

| Comments

“Well, I was born in a small town / And I can breathe in a small town / Gonna die in this small town / And that’s prob'ly where they’ll bury me”

–“Small Town”, John Cougar Mellencamp

How small is too small?

Making a really small map, we want to make sure characters will actually spawn in it. Unfortunately the spawn positions are actually hardcoded:

DragonsSpine/Menus/CharGen.cslink
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
#region Set Starting Location
switch (ch.BaseProfession) // starting location in the game
{
    case Character.ClassType.Thief:
        ch.LandID = 0;
        ch.MapID = 0;
        ch.X = 51;
        ch.Y = 26;
        ch.Z = 0;
        ch.CurrentCell = Cell.GetCell(0, 0, 0, 51, 26, 0);
        break;
    default:
        ch.LandID = 0;
        ch.MapID = 0;
        ch.X = 41;
        ch.Y = 33;
        ch.Z = 0;
        ch.CurrentCell = Cell.GetCell(0, 0, 0, 41, 33, 0);
        break;
}
#endregion

(To explain: Thieves are neutral, not lawful, so need to spawn a little further away from the Island’s law enforcement.) So 51, 26, 0 and 41, 33, 0 need to exist on map 0. So let’s make a map which encompasses those points:

1
2
3
4
5
6
7
8
9
10
11
<z>0</z> <x>40</x> <y>25</y> <f>light</f> <n>Test01 Surface</n> outdoor=true
WWWWWWWWWWWWWWWWWWWWWWWWWW
WW. . . . . . . . . . . WW
WW. . . . . . . . . . . WW
WW. . . . . . . . . . . WW
WW. . . . . . . . . . . WW
WW. . . . . . . . . . . WW
WW. . . . . . . . . . . WW
WW. . . . . . . . . . . WW
WW. . . . . . . . . . . WW
WWWWWWWWWWWWWWWWWWWWWWWWWW

Make that map our map 0:

EntireDB-test02.sqllink
818
INSERT [dbo].[Map] ([mapID], [landID], [name], [shortDesc], [longDesc], [suggestedMaximumLevel], [suggestedMinimumLevel], [pvpEnabled], [expModifier], [difficulty], [climateType], [balmBushes], [poisonBushes], [manaBushes], [staminaBushes], [resX], [resY], [resZ], [thiefResX], [thiefResY], [thiefResZ], [karmaResX], [karmaResY], [karmaResZ], [randomMagicIntensity]) VALUES (0, 0, N'test01', N'test01', NULL, 12, 3, 0, 1, 1, 2, 1, 1, 0, 0, 41, 26, 0, 42, 27, 0, 43, 28, 0, 0)

And make sure the character spawns are in valid locations, and move the dog spawn, and move the cell description, and move the one player, etc.

Speaking of hardcoded server issues, the path to the maps is ..\..\maps, so we need to set up out test environments accordingly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
./maps:
test01.txt

./test_env:
test02

./test_env/test02:
DragonsSpine.exe
DragonsSpine.exe.config
GameLib.dll
Logs
Net.dll

./test_env/test02/Logs:

Alter that config to point to my test DB, run that executable, and voilĂ !

No live data?

Despite this great success, nothing’s showing up in the LiveCell table. We only push the previous round’s cell changes when there is a cell change in the current round, and none of the cells on this map ever change past round 0. In any normal map we could depend on a door being opened, something being dropped, etc in the first couple of rounds; but there’s nothing going on in test01.

My initial solution:

DragonsSpine/DAL/DBWorld.cslink
152
153
154
155
156
157
internal static int SaveLiveCell(Cell cell) {
    int result = 0;
    lock (lockObjectLiveCellUpdate) {
        // To keep from having no data if nothing ever changes, we'll just hit the DB with every change in the first round.
        if ((DragonsSpineMain.GameRound != DAL.DBWorld.roundToUpdate) || (DragonsSpineMain.GameRound == 0)) {
            try {

But for non-trivial maps, that’s an awful lot of individual database connections on the first round. Let’s just actually force a push of what’s queued up at the beginning of round 1:

DragonsSpine/DragonsSpineMain.cslink
700
701
/* Save live Cell data on round 1, to handle maps with no activity */
if (DragonsSpineMain.GameRound == 1) DAL.DBWorld.SaveLiveCell(null);

Much nicer. And look: And so memory-efficient. At round 5, less than 20mb. At round 50, more like 30mb. At round 100, closer to 40mb. Eventually (500 rounds or so), we stabilize around 100mb; I guess that’s when the garbage collector kicks in more aggressively. For now, I’m satisfied at having lowered the cost of admission for a quick test further.

Tomorrow: Parallel servers?


Day 49 code - tests (well, setup for tests) Day 49 code - server

Comments