Jump to content
  • Advertisement

Project: Unsettled World

A Story of Some Servers and Their Game.

Septopus

817 views

Unsettled World, makes a great title I think, but without a server, it's just a terribly lonely place indeed.

I've written many servers over the years and clients to go with them, and in lots of different languages(never before for games).  However,I've never been one to hang onto the proper semantics of communicating how a program works so, stick in there and I'll do my best. ;)  Please feel free to chime in if you see something technical that could be fixed or if it just looks at you funny, you can tell me that too.  I'm good with it. 

Architecture:

Multiple, functionally segmented, server applications / To many, identically functional clients.  To sum it up..  haha  It's important to say that all servers maintain an authoritative role in all matters of game play.  If the Avatar Server hasn't authorized that item in your inventory, it won't be there.  If the Economy Server has a 0.00 in your bank account, the game client will reflect that.

Avatar Server(Functional in all listed categories): C# UDP server application, game time keeper, controls authentication, resource access, player inventories, land ownership and mining claim ownership and is the "echo point" for network player data such as positioning and appearance data.

Economy Server(Currently in ACTIVE Dev): C# UDP server application, Communicates with the Avatar Server to coordinate time synchronization, and to update its list of active player id#s and their encryption keys. Its purpose is to house all the functionality that one would attribute to a game economy(aside from physical resource access).  Banking, Auctions and a Resource Stock Market.  My Player1 checked the balance on his bank account for the first time just yesterday in fact.  He was pleased to finally see the 2000.00 Settler Credits he was promised months ago.  lol.

NPC Server(s)(Currently Completely Imaginary): C# UDP server application that communicates the positions and coordinates the movements of NPCs that are instantiated into the world by their NPC Client applications.

NPC Client(s)(Currently Completely Imaginary): C#(or c#/unity) UDP Client applications that will control the movement and interactivity of one or many NPCs, all NPC code will interact with the server just like player code does, via a UDP connection.  However, since most of the NPC data will already be built into the client, these connections will be significantly less chatty than a real players connection.

Other Servers/Clients(Also Completely Imaginary): C# probably, UDP most likely.. the rest, who knows. ;)

So, how do I keep all these data bits ready for player interaction?  Data Structures!!  Everything in my servers runs from in-memory data structures, I have no database back end, nor a desire to ever need one.  I'm not saying databases aren't cool, or massively useful in similar scenarios.  I have built MANY of those too, but to get the response times I want, well that would require something in the range of an in-memory instance of mysql or another big hitter similarly configured.  I don't want to have to add that to the arena, and certainly not at this stage of the game.. heh..  stage of the game... Anyway!

Some of the Data Structures Currently Utilized in my Avatar Server:

 //This keeps track of the player ids and encryption strings
 //When a player logs on an encryption string is negotiated...
 Dictionary<int, string> playerKeys = new Dictionary<int, string>();
 
 //Reverse lookup for player ID#s to stored GUID ids.
 //ID#s are shorter and travel better in a compact UDP packet(1470ishbytes) than a big Ol'GUID!
 Dictionary<int, string> playerGUIDLookup = new Dictionary<int, string>();

 //"Table" of currently authenticated Player Save data for many uses here and there, but mostly for persistence purposes.
 //This gets updated by the client when the player makes changes and is saved on the server side.
 //Including the character's avatar description. (Avatar Server)
 Dictionary<int, AvatarSave> PlayerAuth = new Dictionary<int, AvatarSave>();
 
 //Seems redundant somehow, but it isn't. Just, a bad name. 
 //This keeps count of how long a player is idle from the server's perspective, so it can give them the BOOT when it goes too long.
 Dictionary<int, int> livePlayers = new Dictionary<int, int>();
 
 //Seperate "Table" of data specific to the player avatar movements and orientation, position/rotation/etc...
 Dictionary<int, AvatarAttitudeUpd> livePlayerData = new Dictionary<int, AvatarAttitudeUpd>();
 
 //This holds data recieved asynchronously from the game clients(or other servers) as well as the EndPoint it was recieved from, for replies.
 //Each recieved command in this Queue is given a Task to process and reply to the game client with.
 //One message/activity/request/command per packet and only ONE, so no complicated re-assembly is needed on either end of the wire.
 Queue<KeyValuePair<string, EndPoint>> UDPClientMessages = new Queue<KeyValuePair<string, EndPoint>>();
       
 //A less organized version of the above data structure.  These get filtered for players who aren't logged in anymore, commands out of order get skipped, and etc..  Essentially it's the RAW data from the asyncronous receiver.
 Dictionary<EndPoint, Queue<string>> UDPMessages = new Dictionary<EndPoint, Queue<string>>();

 //The collection of all known player IP/PORT end points, that haven't been booted for inactivity.
 Dictionary<int, EndPoint> playerEPs = new Dictionary<int, EndPoint>();

 

Here's a quick run..

Avatar Server Application Starts:
 

udpServerThread = new Thread(new ThreadStart(UDPServer));
UDPServer()
{
 //Starts up a standard UDP Socket Server here with an asynchronous receive mechanism which pumps into the UDPClientMessages Queue.
 	Loops here waiting for clients to send data.
 	while(true)
	{
		Increments Game Time, a double precision counter that keeps track of the total run time of the avatar server. 

		Parallel.ForEach() through the playerEPs sending them them the current server time.
		
		foreach() through the livePlayerData sending all relevant network player data to the clients who should see them.
		
		Some threadpool scaling to increase/decrease the pool size depending on # of users logged in.
		
		Requeueing of messages from UDPMessages into UDPClientMessages happens via some Task.Factor Tasks.
		
		And finally a new Task.Factory Task is created for every item in the UDPClientMessages Queue to process the incoming command from the player's game client.  (player's new coordinates, logins, inventory requests, changes,etc,etc,etc)...
	}
}

 

I can't even call that pseudo-code but I think it conveys what I'm trying to share without going into too much gory detail.  If anybody wants some of that, feel free to comment below and I'll expand on anything I can.  But this describes the basic conceptual design of my server applications.

There are whole other layers of data structures in that server that I've omitted as it gets extremely gory in there...  But that's where the inventories / resources / and crafted items live and it's a bit messy right now.  I'm going to try to get those a little bit more finalized before I try to convey their madness to you.  Suffice to say, there's a lot more to it than this.  But that is less related to the "server" and more related to the game.

Until next, Thanks for reading!




0 Comments


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Advertisement
  • Blog Entries

  • Similar Content

    • By horror_man
      Hello, I'm currently searching for a talented and passionate programmer to create a small but great horror game that would take around 3 months to be done.
       
      About the game: The game would be a sci-fi/post-apocalyptic survival horror 3D game with FPS (First person shooter) mechanics and an original setting and story based in a book (which I'm writing) scene, where a group of prisoners are left behind in an abandoned underground facility. It would play similar to Dead Space combined with Penumbra and SCP: Secret Laboratory, with the option of playing solo or multiplayer.
       
      Engine that'd be used to create the game: Unity
       
      About me: I'm a music composer with 4 years of experience and I'm fairly new in this game development world, and I'm currently leading the team that'd be creating this beautiful and horrifying game. I decided that making the book which I'm writing into a game would be really cool, and I got more motivated about doing so some time ago when I got a bunch of expensive Unity assets for a very low price. However, I researched about how to do things right in game development so I reduced the scope of it as much as I could so that's why this game is really based in a scene of the book and not the entire thing (and also that's why it would take 3 months). Also I'm currently learning how to use Unity and how to model things with Blender.
       
      Our team right now consists of: Me (Game Designer, Creator, Music Composer, Writer), 3 3D Modelers, 1 Sound Effect Designer, 1 Concept Artist and 1 Programmer.
       
      Who am I looking for:
      - A programmer that's experienced in C# and with Unity.
       
      Right now the game is very early in its development (GDD is completed and all 3D Items, Music and Sound Effects are completed).
       
      If you are interested in joining, contributing or have questions about the project then let's talk. You can message me in Discord: world_creator#9524
    • By bertan otun
      I need help, I just started learning today (about programming). But I dont understand what I am doing wrong I am getting a error message: Assets/PlayerMovement.cs(10,9): error CS0117: UnityEngine.Debug' does not contain a definition forlog' I found the problem (its about the captials.)
    • By MiniDarkOF
      [I accept: tutorials, videos, blog posts, scripts, any help is useful]
      [Preferably, if you are sending scripts to help please in C#]
      (i already created a post in a discord server, so i'll attach the post print)

    • By mtjscott
      Hey, so i've created a disk in unity (2D mobile) that will be shot forward if you drag it back and the further you drag it from the start point the more force will be applied to the impulse similar to the 8ball pool drag to shoot mechanic on miniclip. However, when I applied a script that allows the main camera to follow the ball it broke the mechanic since the balls position is calculated through the camera in world space. So I created a bool that locks the camera in place until the ball is released so the calculation would happen before the camera starts to move. This works however the ball now rubber bands back and forwards close to the start position.
       
      If anything needs more explaining then i'd be glad to do so. I've only been coding for about a week so you'll have to bare with me. Any help is appreciated. Thank you very much.
       
      Here's What happens:
      https://gyazo.com/f211e50f32ac59437a93dad7295a14be
      (screencap gif of the game viewer)
       
      Here is the shoot script:
      using System.Collections; using System.Collections.Generic; using UnityEngine; public class Shoot : MonoBehaviour { [SerializeField] GameObject Disc; [SerializeField] float multiplier; Vector3 initPos; private Rigidbody2D rb; public static bool ballIsReleased = false; bool recordingDistanceDragged = false; private void Start() { rb = gameObject.GetComponent<Rigidbody2D>(); initPos = transform.position; } void OnMouseDrag() { recordingDistanceDragged = true; if(recordingDistanceDragged == true) { transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10)); } else { transform.position = initPos; } } void OnMouseUp() { ballIsReleased = true; } private void FixedUpdate() { if(ballIsReleased == true) { rb.AddForce((initPos - transform.position) * multiplier, ForceMode2D.Impulse); Debug.Log("ball is released"); recordingDistanceDragged = false; } else { ballIsReleased = false; } } }  
      Here is the camera follow script:
      using System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraFollow : MonoBehaviour { private Vector2 velocity; public float smoothTimeY; public float smoothTimeX; public GameObject player; private void Start() { player = GameObject.FindGameObjectWithTag("Player"); } private void FixedUpdate() { if (Shoot.ballIsReleased == true) { Debug.Log("camera can move"); float posX = Mathf.SmoothDamp(transform.position.x, player.transform.position.x, ref velocity.x, smoothTimeX); float posY = Mathf.SmoothDamp(transform.position.y, player.transform.position.y, ref velocity.y, smoothTimeY); transform.position = new Vector3(posX, posY, transform.position.z); } } }  
    • By Nilmani Gautam
      Welcome everyone, this is the last video on section and end of our Terminal Hacker game. In this video we will learn to create random number. 
      And from our next section we will create 3d game 
      We will create CUBE RACE for our lesson.
       
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!