Jump to content

Dev Diary - The making of a client/server text adventure engine


  • Please log in to reply
2 replies to this topic

#1 Guest_ElatedOwl_*

Guest_ElatedOwl_*
  • Guests

Posted 15 August 2012 - 05:14 PM

Preface
You're probably wondering what the purpose of this thread is. When you develop something, it's nice to keep a record of where you are, where you've been and why you did what you did. In software it's generally stated that your first implementation of something is absolute garbage, and the second (or beyond) is the "golden code". I'm too lazy to set up a blog, so this is a good place for me to do this kind of thing. It also helps to write it to an audience (who has no guarantee to understand what you're talking about), too often do people I write myself notes only to have no idea what I meant later. Is this of any value/entertainment to you? Probably not. :x

Introduction
A multiplayer, client-server text adventure game platform. The original iteration should be an engine moreso than a game.

Requirements
  • Re-implementable. Anyone with an understanding of SQL and basic networking (port forwarding, firewall) should be able to deploy a server.
  • Friendly client. The server requires a little background knowledge, but the client itself should be extremely easy to use.
  • Keep remote connections in mind. Handle AFK players, disconnects etc. gracefully.
  • Clean and customizable. Any experienced C# dev should be able to write their own code and modify the engine without wanting to pull their hair out.
  • No third party dependencies.
Outline
  • Simplistic GUI. A text area that outputs the story, a textarea below to enter commands, a party window (for sake of usability) and inventory window.
  • MSSQL backend. Absolutely no inline queries, only stored procedures.
  • Map contains three main classes
1. Zone
  • Title
  • Description
  • ID
  • A list of tilesets that the zone contains. (possibly a dictionary, key could be floor# and value could be the tileset)
  • Can possibly house zone wide debuffs, auras, missions
2. Tileset
  • Title
  • Description
  • ID
  • List of tiles (generic list should do)
  • Auras (debuffs, w/e)
3. Tile
  • Events (generic triggers such as possible fight, treasure, or specific story events)
  • ID
  • Coords (An X, Y entry)
  • Walls (A set of 4 booleans for each cardinal direction indicating if the path is accessible; perhaps not boolean, destructible walls or one way walls are a possibility)
  • Coords and Walls can determine any available neighbors. Perhaps a list of tile IDs can cache neighbors so it isn't a heavy calculation each step on large tilesets.
Monsters should probably each be their own inherited class/interface or whatever. That way you can have a set of basics that are easy to make new ones, but the ability to create unique creatures/bosses as well.

More later...

#2 Wolf

Wolf

    Zettabyte

  • Members
  • 6,487 posts

Posted 16 August 2012 - 05:59 PM

I wanna use it, if just for the hell of it.

I recommend, in an online setting, having any player speech take place in onscreen area separate from the text displaying what the player is doing/has done

I like the boolean walls, too

#3 Guest_ElatedOwl_*

Guest_ElatedOwl_*
  • Guests

Posted 31 August 2012 - 09:16 AM

Challange 1 - Sockets

This is what allows network communication (ie, online multiplayer). .NET makes life a lot easier and has a built in asynchronous socket class, so listening to for a connection and setting up events is a brain dead easy.

Sending Data
Data is sent in an array of bytes. Bytes are an 8-bit integer, a number between 0 and 255. By default I'm going to use a buffer size of 1024, that is, an array of 1024 bytes. The server will have to send lengthy-ish messages describing the current environment to the user, will have to issue certain commands (such as party status, kick player, etc). I don't imagine I'll exceed 256 commands, so our first packed byte will be the command, followed by any text we're sending (specific parameters for the command, text to display, etc.) and since some messages are going to inevitably exceed the buffer, the end of the params/messages will contain <EOF> so it knows its done with the message.

The other course of action I could take to avoid messy string command interpreting is serializing native objects. It makes the overhead a little larger, but how much larger?
I set up a simple object to compare how many bytes serialization causes vs. string parsing params. Note that this is serialized by the built in BinaryFormatter.

[Serializable]
	public class testObj
	{
		public string test1 { get; set; }
		public int test2 { get; set; }
		public bool test3 { get; set; }
	}


testObj test = new testObj();
test.test1 = "This a test string. It tests strings.";
test.test2 = 255;
test.test3 = true;


The object serializes out to 247 bytes.
If I were to send it over manually, the command string would look something like
<~>test1<~>This is a test string. It tests strings.<~>test2<~>255<~>test3<~>true<~><EOF>

Which is 176 bytes, 177 including the command at the beginning. The other thing to consider is that the each parameter has no idea what data type it is.

I think I'll sacrifice a bit of the network for the ease of my life and performance on the client.