Jump to content


Photo

Passion Project: Whispering Winds: Chronicles Of The Ethereal


  • Please log in to reply
4 replies to this topic

#1 PureMourning

PureMourning
  • Members
  • 610 posts

Posted 25 September 2023 - 07:07 PM

Hi fellow Nightmistians!
 
It's been a hot minute since I've played but I've always been a forum-lurker.  It's pretty quiet around here, but I thought I'd share information about a project I'm working on.
 
A little background . . . 
 
I'm sure most of us are in our 30s at this point, decades removed from the heyday of falling in love with and playing this game at its peak.  I've been working professionally in the cybersecurity field for several years, and a big chunk of of that time has been in engineering roles.  To be clear, I am by no means a professional software engineer, but I know enough to be dangerous (in my field I equate "engineering" to scripting, automating tasks, performing log analysis, etc.)  
 
Python is very popular in security and I've recently been working on building up my chops.  I got the crazy idea that it may be fun to practice Python by attempting to build a text-based RPG game, like of course, our beloved Nightmist.  I started to think things like, "How is a game light Nightmist built?"  "How does the client-server architecture work?"  "What modern technologies would I use to build the basics of a game?"
 
I recently started building the foundations of a project that I thought would be fun to share with you -- especially if any of you are like me -- and have been even remotely curious as to what goes into building a game like this.
 
A little bit of housekeeping . . .
 
to staffers (whoever you are now-a-days):  I don't recall the rules re: advertising other games, but rest assured, my passion project is extremely non-playable and there's a good chance it will never be playable, so I hope you don't take this as advertising another game.  I simply want to share my adventures in learning how to build a full-stack app/game that exhibits fun mechanics that are inspired by Nightmist.  It may be fun to engage in a bit of conversation around design choice, tech stack, game mechanics, etc.
 
Introducing Whispering Winds: Chronicles of the Ethereal:
 
I just started the project last week and wanted to see if I could even get to the point of building out the simple mechanic of allowing players to log in and move around a basic world.  Before jumping into the code, I contemplated which language/tooling would best suit my needs.  Inspired by Python, I decided that writing the core game logic in Python was a no-brainer.  Shortly thereafter, I thought it would make sense build the web app in Flask, a micro web framework written in Python.
 
Here is diagram that represents the full current tech stack that I am using:
https%3A%2F%2Fprod-files-secure.s3.us-we
 
 
As you can imagine, I've quickly learned that there's so many details that go into building even the most basic systems:  understanding web sockets, how to handle constant bi-directional communication between the client and server, and how to persist game data using a database.

I've probably put in ~10-15 hours within the last 5 days building the very basics.  I've been keeping a progress log/screenshots and thought it'd be fun to chronicle them here:

https%3A%2F%2Fprod-files-secure.s3.us-we

 

After that basic client-server connection was handled, I started thinking about a simple grid system to handle the various areas that may exist.  I built a simple x,y grid system and the foundation of movement:

Untitled.png?id=2e1b5e75-2184-4af3-bb74-
 

Then I wanted to cleanup the UX and make it more clean and starting building placeholders for things like character info, inventory, etc.

Untitled.png?id=2c3eb588-8d10-419a-b0b4-

 

 

In this final screenshot, you'll notice that the movement system is starting to evolve and its process has been the most profound for me so far.  For example, after building the basics of movement I realized, "Oh, crap. How do I handle telling Player A that Player B left the grid?"  This got me into a rabbit hole of understanding how webs sockets work, and in particular, how functionality within Flask's SocketIO library operates.  It took me a few hours to understand the concept of connected clients (players) being in a various "rooms", which represent how a player can receive communication.  I learned that each grid/room in the game needs to have its own socket "room" for sending messages to specific areas.

Untitled.png?id=b6738d4b-7c41-43e6-805e-

 

 

 

As of today, a player can create an account, create various characters, log in, chat, and move around a basic area called "Town Square".  There's a ton I want to add and I'm certain I'll make a million more mistakes.  I am working on adding items/inventory system and finessing the movement.

If I happen to make further progress - and if anyone is interested in more of behind-the-scenes game building a logic - I may post again!


Edited by PureMourning, 25 September 2023 - 10:47 PM.

Cogito, ergo sum; I think, therefore I am.

#2 Stig

Stig
  • Game Staff
  • 1818 posts

Posted 25 September 2023 - 10:08 PM

The image links say "Access Denied" when I try to open them.



#3 PureMourning

PureMourning
  • Members
  • 610 posts

Posted 25 September 2023 - 10:48 PM

The image links say "Access Denied" when I try to open them.

 

Ah, apologies, Stig!

I realized there was a permissions issue with how I was hosting/sharing the pics.  I've updated the original thread and the pics should be there!


Cogito, ergo sum; I think, therefore I am.

#4 PureMourning

PureMourning
  • Members
  • 610 posts

Posted 28 September 2023 - 05:39 AM

apologies for some of the screenshots being jacked in the OP -- stupid expiry on the images I exposed within my note-taking app -- but missing/new screenshots below!  :)  }
 
But first . . . a quick insight into the last 2 days:
 
I've been in session management hell the past ~48 hours.  I noticed a fatal security flaw that allowed Player A to access Player B's character despite having authentication methods in place during login.
 
It only made sense early on to add a login screen that was equipped with the usuals:  allowing players to enter a username, password, and ensuring that those two things checked out.  At the time of my original post, I had already built the backend logic/respective database schema to facilitate this:  I even made sure to store user passwords as hashes in the database, and in turn, check the user's inputted hashed password against what is stored in database, etc.
 
Upon successful login, a player enters the main game after selecting a character.  In the original code, the initial bi-directional socket connection was established after running the login checks, which meant, that another player could connect to another player's character if that knew a.) the correct route / URL for hitting the main game and b.) another player's character ID -- which would be easy to brute-force if they didn't explicitly know it.
 
I made the realization that I wasn't doing any sort of session management!  In other words, I was not keeping track of session information on a per user basis as it pertains to active connections to the server.
 
I changed the database's users schema to start tracking session IDs at the point in which a player establishes a new connection.  I also wanted to do all of this in a way that aligned to two key requirements:
 

  • Ensure only one character can be played at a time
  • Mitigate Player A from accessing Player B's character

I believe I've solved for both of these (well at least in the context of realistic expectations considering I am running the game on a local server without SSL/TLS) and think I have made it out of session hell.  It was fascinating trying to understand how to create and track session data across the entire app, both backend and frontend.  The way the login sequence works entails the client technically making two distinct connection requests to the server so I had to come up with a creative/hacky way to make sure both requests were tied to a singular session ID.
 
I ended up using Flask's built-in server-side session storage capability to save/load the initial connection data and then re-construct it at the time the game loads, ensuring that the session ID is consistent despite there being two distinct connection events:

Some code examples for you fellow nerds:
 

const serializedSocket = serializeSocket(window.socket);sessionStorage.setItem('socket', JSON.stringify(serializedSocket));

The really interesting part is that I also ran into issues trying to retrieve the stored socket information into JSON format due to "circular" behavior with its member attributes.  So I created a helper function to serialize/de-serialize it:
 

const serializedSocket = JSON.parse(sessionStorage.getItem('socket')); 

// Check if the socket data exists and is connected
if (serializedSocket && serializedSocket.connected) {
    // If a connected socket exists, use it
    console.log("Connected socket exists.")
    socket = deserializeSocket(serializedSocket);
} else {
    // If no connected socket exists, create a new one
    console.log("Connected socket DOES NOT exist.")
    socket = io.connect('http://localhost:5000');
}

//Helper function:
// Deserialize the socket object
function deserializeSocket(serializedSocket) {
     // Create a new socket object and set its properties
     const socket = io.connect('http://localhost:5000');
     socket.on('connect', function(data) {
         socket.emit('send_sid', socket.id)     
     });
     if (serializedSocket) {
         socket.id = serializedSocket.id;
         socket.connected = serializedSocket.connected;
     }
     return socket; 
}

Missing screenshots from OP:
 

 After that basic client-server connection was handled, I started thinking about a simple grid system to handle the various areas that may exist.  I built a simple x,y grid system and the foundation of movement:

 
https%3A%2F%2Fprod-files-secure.s3.us-we
 

 
Then I wanted to cleanup the UX and make it more clean and starting building placeholders for things like character info, inventory, etc.

 
https%3A%2F%2Fprod-files-secure.s3.us-we
 

 
 In this final screenshot, you'll notice that the movement system is starting to evolve and its process has been the most profound for me so far.  For example, after building the basics of movement I realized, "Oh, crap. How do I handle telling Player A that Player B left the grid?"  This got me into a rabbit hole of understanding how webs sockets work, and in particular, how functionality within Flask's SocketIO library operates.  It took me a few hours to understand the concept of connected clients (players) being in a various "rooms", which represent how a player can receive communication.  I learned that each grid/room in the game needs to have its own socket "room" for sending messages to specific areas.

 
https%3A%2F%2Fprod-files-secure.s3.us-we
 
NEW Screenshots:
 
Spruced up login:
https%3A%2F%2Fprod-files-secure.s3.us-we
 
Cleaned up movement behavior and started adding basics of an inventory system:
https%3A%2F%2Fprod-files-secure.s3.us-we
 
 
Created an image for the initial "Town Square" and put it in the main game's background.  I also had a cool idea to change the game's background every time you go to a new area.  Something for the future, perhaps . . . 
 
https%3A%2F%2Fprod-files-secure.s3.us-we
 
So much to do!


Edited by PureMourning, 28 September 2023 - 05:35 PM.

Cogito, ergo sum; I think, therefore I am.

#5 PureMourning

PureMourning
  • Members
  • 610 posts

Posted 11 October 2023 - 06:37 AM

Hi all,

 

I've been working on the project virtually every day the past ~2 weeks since the last update and wanted to share what I've been up to:

 

In keeping with "KISS" (Keep It Simple Stupid), I've decided to start with races and 4 classes:

 

  • Humans, Elves, Dwarves and Orcs
  • Warriors, Mages, Clerics and Rogues
     

Want constant behind-the-scenes-updates?: There's almost daily dialog in the Nightmist Discord server's off-topic channel if you want to see more frequent updates and behind-the-scenes conversations (even the mighty Pandilex has been giving me tips on design decisions, etc.)

 

 

You can view recent progress pics here:  https://fallacious-s...623a6a6dc67472d

 

 

Key items you'll see in the link above:
 

  • I've been working on adding the basic constructs of monsters, their attacking behavior (which is varied based on "aggressiveness" levels) and how they appear in the UX.  You can hover-over and get real time-data on mobs, like their health
     
  • I've also been adding the inventory and equipment system, to include right-click context menus that allow you to inspect item

 

Screenshots for those who don't want to click links :P

https%3A%2F%2Fprod-files-secure.s3.us-we

 

 

https%3A%2F%2Fprod-files-secure.s3.us-we

 

https%3A%2F%2Fprod-files-secure.s3.us-we

 

https%3A%2F%2Fprod-files-secure.s3.us-we

 

Take care!


Edited by PureMourning, 11 October 2023 - 06:40 AM.

Cogito, ergo sum; I think, therefore I am.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users