Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

126 Neutral

About trill41

  • Rank

Personal Information


  • Github
  1. trill41

    WinAPI Raw Input confusion

    DirectInput was also for Keyboard and Mouse. Forget what I wrote about XInput, XInput1_3 works on Win7, I must have been confused, sorry.
  2. trill41

    WinAPI Raw Input confusion

    I agree on that. And I also don't see any direction Microsoft is heading to, there was DirectInput then XInput (not running on Win7 without hacks), Window messages etc. All is more or less deprecated. It is the same mess as for UI development for Windows, Win32 API, MFC, WinForms, WPF etc. Again all more or less deprecated, and Microsoft doesn't give any direction. This is really an unfortunate situation.
  3. trill41

    WinAPI Raw Input confusion

    Microsoft suggests to use the default Windows messages, even for games (I read it somewhere but forgot where, but it makes sense). I would forget raw input and just use the default window messages. In your WndProc you could do something like this: switch (message) { case WM_MOUSEMOVE: OnMouseMove((DWORD)wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_XBUTTONDOWN: OnMouseDown((DWORD)wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_XBUTTONUP: OnMouseUp((DWORD)wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; case WM_MOUSEWHEEL: OnMouseWheel((DWORD)wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), GET_WHEEL_DELTA_WPARAM(wParam)); break; case WM_KEYDOWN: case WM_SYSKEYDOWN: OnKeyDown((DWORD)MapLeftRightKeys(wParam, lParam)); break; case WM_KEYUP: case WM_SYSKEYUP: OnKeyUp((DWORD)MapLeftRightKeys(wParam, lParam)); break; // ... default: return DefWindowProc(hWnd, message, wParam, lParam); }
  4. trill41


    This is an RPG and RPGs usually have skills. In this game a character can have up to eight skills. NPCs and Players usually can equip skills from the same pool. But I'm not yet sure if this game will have a PvE part, where you fight against NPCs, or if it's just a PvP game. Anyway, NPCs can have and use skills. Skills There should be different types of skills, skills that make damage to a target or make AOE damage. Other skills can heal a target or all Actors in an area, etc. All this should be controlled by the Lua script, the server itself has no knowledge what a skill does, and the Client, well, the Client knows nothing. The basic effect of a skill can be: Resurrect Heal Protect (avoid, reduce damage) Damage And a skill can have an effect to: Self Selected Target AOE So a single skill can have one or more of the above effects and one or more of the above listed targets. At the moment the skill pool is very limited, there are just three skills: Sudden Death (instant suicide): Targets self and makes damage. Instant Kill: Targets the selected target and makes damage. Instant Rezz: Targets the selected target and resurrects. All these skills are only for testing and don't make sense in a real game. Skills scripts Skills are implemented as simple Lua scripts, like bellow the "Instant Kill" skill: -- Use own include function, because the Lua search path is a mess -- and it makes it possible to precompile and cache the script include("/scripts/includes/consts.lua") include("/scripts/includes/skill_consts.lua") costEnergy = 0 activation = 0 recharge = 0 range = RANGE_MAP -- If there will be some AI then the AI must have some basic knowledge of what a skill does effect = SkillEffectDamage | SkillTargetTarget function onStartUse(source, target) if (target == nil) then -- This skill needs a target return false end if (source:GetId() == target:GetId()) then -- Can not use this skill on self return false end; if (self:IsInRange(target) == false) then -- The target must be in range return false end if (target:IsDead()) then -- Can not kill what's already dead :( return false end return true end function onEndUse(source, target) -- print("Using Instant Kill on " .. target:GetName()) return target:Die() end function onCancelUse() end Of course, this skill is a bit overpowered, but it's just for testing. Player using skills A player has a skillbar, usually at the bottom, with all equipped skills: As almost any action in this game, a hotkey can be assigned to each skill, but is also triggered when the button is clicked. NPC using skills In the same way a player uses skills, NPCs can use skills. They also have a skillbar with max. eight skills. To make this work the NPC Lua scripts have to be extended, like the Pedestrian, to make her Rezz machine: include("/scripts/includes/chat.lua") include("/scripts/includes/consts.lua") include("/scripts/includes/skill_consts.lua") name = "Pedestrian" level = 20 modelIndex = 10 -- Female Pedestrian 1 body model sex = SEX_FEMALE creatureState = CREATURESTATE_IDLE prof1Index = 3 -- Monk prof2Index = 0 -- None --behavior = "wander" local rezzTarget = nil function onInit() self:SetSpeed(0.5) -- Let's make it a rezz machine :D local skillBar = self:GetSkillBar() -- Instant rezz skill skillBar:AddSkill(9996) return true end function onUpdate(timeElapsed) if (self:IsDead() == false and rezzTarget == nil) then local actors = self:GetActorsInRange(RANGE_CASTING) for i, v in ipairs(actors) do if (v:IsDead()) then rezzTarget = v break end end if (rezzTarget ~= nil) then self:FollowObject(rezzTarget) self:Say(CHAT_CHANNEL_GENERAL, rezzTarget:GetName() .. ", you noob!") end end end function onClicked(creature) end -- self was selected by creature function onSelected(creature) self:Say(CHAT_CHANNEL_GENERAL, "Not now!") end -- creature collides with self function onCollide(creature) end function onArrived() -- self:FollowObject(rezzTarget) was called to go to the target. Now she is there. if (rezzTarget ~= nil) then local skillBar = self:GetSkillBar() local skills = skillBar:GetSkillsWithEffect(SkillEffectResurrect) if (skills[1] ~= nil) then self:SetSelectedObject(rezzTarget) self:UseSkill(skills[1]) end rezzTarget = nil end end function onEndUseSkill() rezzTarget = nil self:SetState(CREATURESTATE_IDLE) end function onStartUseSkill(skill) local targetName = "Everything!" local target = skill:GetTarget() if (target ~= nil) then targetName = target:GetName() end print("Using skill " .. skill:GetName() .. " on " .. targetName) end function onDied() self:Say(CHAT_CHANNEL_GENERAL, "Aaaaarrrrrrggghhh") end function onResurrected() self:Say(CHAT_CHANNEL_GENERAL, "Oh, ty") end This NPC will go to dead people if they are in a certain range, and will resurrect them. Video
  5. trill41

    Scaling and Administration

    The Game server doesn't scale vertically (i.e. throw better hardware at a problem) well, because it's mostly single-threaded, so it can host only a limited amount of concurrent games. The second option is to make it scale horizontally (throwing more hardware at a problem) well, so make it possible to spawn/shutdown Game servers dynamically across different hardware. Only the File and Game server are meant to be spawned dynamically. All other server are needed that these servers can work together. For this I made an Admin interface (btw. meanwhile I'm no longer sure what's this all about, is it a game server or a framework for scaleable servers?), which can spawn Game and File server as needed. Oh yes, I wrote a Web server for it, based on SimpleWeb which is also used for the File server, and it uses a nice Bootstrap theme (Gentelella Admin). I just added support for Cookies, Sessions and it has simple templating, because I don't want to write Markup in C++. Hell, I totally forgot how fast a Web server can be, like response times under 1ms. A central part in this process takes the Message server, which is for inter-server communication. It works like a Chat server, Clients connect to it and can broadcast messages to all other connected clients, or they can send a message to a certain client identified by its ID. A server can only spawn another instance of itself, it can not spawn a different server, like a File server can not spawn a Game server. So there is a persistent (master) server that can be told to spawn child servers, and it'll do so. Exactly this is happening when clicking the green Spawn button. The Admin server sends a message to the Message server, which forwards the message to this particular server and this is spawning a new server of the same type with the same configuration. Well, with almost same configuration, of course it needs a unique ID (I use UUIDs), a unique Name and it must use a free Port. To get a free Port, this is what works for me: uint16_t GetFreePort() { asio::io_service service; asio::ip::tcp::acceptor acceptor(service); uint16_t port(0); asio::ip::tcp::endpoint endPoint(asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port)); acceptor.open(endPoint.protocol()); acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true)); acceptor.bind(endPoint); acceptor.listen(); asio::ip::tcp::endpoint le = acceptor.local_endpoint(); port = le.port(); acceptor.close(); return port; } Shutting down a server is different, it can stop only itself. So if one server wants to shutdown another server, it sends a message to the message server, which sends the target server a message to stop itself. Even a "Master" server can not shutdown a child process, it would need to send a shutdown message to the Message server.
  6. Microsoft Docs (https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getdlgctrlid) say: You call CreateWindow (https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createwindowa) with NULL as hMenu, so it has the ID 0 and this is what the function returns.
  7. trill41

    Migrating and Porting

    Migrating the Database For some reason I thought it would be a good idea to migrate the database from MySQL to PostgreSQL. Installing PostgreSQL on Debian (in my case Debian 8 Jessie) is just one command line. I also made a simple backup script which is run by a chron job, I have a similar script for MySQL: #!/bin/sh # sudo crontab -e # Backup all PostreSQL databases every day 3 am #* 3 * * * /mnt/sda1/bak/pgsqlbak.sh TIMESTAMP=$(date +"%F") BACKUP_DIR="/mnt/sda1/bak/pgsql/$TIMESTAMP" USERNAME="my_name" export PGPASSWORD="*********" find /mnt/sda1/bak/pgsql/ -maxdepth 1 -type d -mtime +7 -exec rm -Rf {} \; mkdir -p $BACKUP_DIR databases=`psql -h -U $USERNAME -q -t -c "SELECT datname FROM pg_database" | sed -n 4,/\eof/p | grep -v rows\) | grep -v template0 | grep -v template1 | awk {'print $1'}` for i in $databases; do /usr/bin/vacuumdb -z -h -U $USERNAME $i >/dev/null 2>&1 /usr/bin/pg_dump -U $USERNAME -i -F c -b $i -h -f $BACKUP_DIR/$i.backup /usr/bin/pg_dump -U $USERNAME -i -F p -b $i -h -f $BACKUP_DIR/$i.sql done Migrating the database structure required some manual work, but fortunately the database is still very small. So I just used mysqldump to get a SQL file, changed some types and syntax and imported it into PostgreSQL. Because I use a caching data server, which is the only program that accesses the database, and this data server is database agnostic (so i can just switch back to MySQL with changing the configuration file), I can not use any advanced database features anyway. This made the migration of the database much easier. I can't even use auto incremented values for primary keys or other database generated values, instead it uses UUIDs as primary keys. The PostgreSQL backend was never tested before, so it surprised me a bit that the data server worked without any changes with PostgreSQL. Porting the Data server I am developing this with MSVC 2015 on Window 7 64 Bit, x86_64 architecture (I also tried VC2017 but the linker crashes all the time). The target is Debian 8 on ARMv7 (32 Bit) architecture. So, not just that the target is a different tools chain, but also the OS and architecture is different. To generate the make files (and VS solution, project files) I use premake5, because I'm not smart enough for CMake. Compiling I didn't compile anything on Linux in ages, so I thought this could be fun. Getting the source to compile with GCC and Clang was not hard, every library I use is also available for Linux, or also compiles on Linux (Lua, SQlite, Asio). What I needed to do was: Just ignore many unknown pragma warnings. Get rid of MS' secure CRT functions (e.g. sprintf_s() -> sprintf()). Get rid of the nifty #pragma comment(lib, ...) and add the lib files to the project and make files instead 😟. Throw out the ODBC database driver. I thought about also targeting MSSQL, so it seemed to be a good idea to have support for ODBC, but it's not used. Turn off Linktime Optimization (full program optimization). Took me a while until i realized my compiler does not support it. Linking So making the program just to compile was very easy, but making it also link was a pain, especially the PostgreSQL client library has many dependencies (e.g. libldap2-dev, libssl-dev, libgsasl7-dev). So I ended up having something like this in my premake5.lua: if (_TARGET_OS == "windows") then links { "abscommon", "abcrypto", "sqlite3", "libpq", "libmysql" } elseif (_TARGET_OS == "linux") then links { "pthrerad", "abscommon", "abcrypto", "sqlite3", "dl", "pq", "ssl", "crypto", "mysqlclient", "z", "gssapi_krb5" } end Finally it complied and linked, but there are still some problems as you can see on the screenshot. It runs now on the same machine as the database server. The data server is very lightweight (without load 🤣😞 Update The linking issues have been solved with upgrading VS2017 to version 15.8.6. Now everything (18 projects) compile, link and run fine with VS2017. Also the obvious bugs on Linux have been solved, but the Linux version of the data server is still not reliable.
  8. trill41

    Part 4: Portals and UI changes

    Portals In games you find something that take you to other maps, sometimes this is called a Portal. On the server side Portals are just scriptable objects like NPCs. The game script adds Portals like it would add an NPC: -- Game start up function onStart() local portal = self:AddNpc("/scripts/creatures/logic/portal.lua") if (portal ~= nil) then -- Map ID where this portal leads to portal:SetVarString("destination", "75e3dfcf-479a-11e8-ad09-02100700d6f0") -- Will call onTrigger() when it collides portal:SetTrigger(true) -- Set position of portal local x = -20.059 local z = -0.00870347 local y = 26.7 portal:SetPosition(x, y, z) end -- ... end The script for the portal is similar to a script for an NPC: name = "Temple of Athene" level = 20 modelIndex = 11 sex = 0 creatureState = 1 prof1Index = 0 prof2Index = 0 function onInit() -- Player collides with BB. Make it a bit larger than the default BB. self:SetBoundingBox(-1, -1, -1, 1, 1, 1) return true end function onTrigger(creature) local player = creature:AsPlayer() if (player ~= nil) then player:ChangeGame(self:GetVarString("destination")) end end The process for changing a game instance is a bit complicated. The player is only connected to the game server when he/she is in a game instance. When you click on a map in the map window the client disconnects from the game server and connects to it again, telling the game server which map it would like to access. The game server creates an instance of this map, and adds the player to this instance. A Portal is a bit different, because the server initiates the switch to a different map. Also we must distinguish whether the client enters an existing instance—which is always the case when using the map window and the instance is not full, because these are outposts where people can meet—or the server creates a new instance. This is the case when entering a battle field, which is exclusive for a party or two, e.g. a PvP combat. But when it comes to gameplay and game mechanics, nothing has been implemented yet. Video UI changes Several small changes to the UI were made. The people from Urho3D have updated the UI texture and styles, which I really like, it is so friendly and ... green xD. A big Thank You to the Urho3D developers for this great library! Additionally the position of the health bar above the characters looks now more natural and speech bubbles have been added.
  9. trill41


    Oh, Urho is awesome! It's really easy to use, has everything I need, the code is very clean, even I can understand it. In my opinion one of the best "Code-First" Engines out there. Well, I think the 100 years is a realistic estimation (although I'm not good in estimating things). It's just huge, and I lack most of the required skills (Story, 3D modelling, animating, texturing, sound/music), I'm just a programmer. Thanks for your comment :)
  10. trill41

    Part 3: UI and Network

    Preface Sorry for the weird order, this is partly chronological and partly what came out of my mind. UI I'm not really a frontend guy, give me some backend service nobody will ever look at, and I'm happy. But since RPGs usually have a rich GUI (Chat, Party, some kinds of Maps, Options etc.) and I'm doing it alone, I'll have to do it. After messing around a lot with Urho3D's UI, I think slowly I get used to it. I even tried Nuklear but realized it's not what I needed due to its immediate mode nature, and the code ends up to be a bit spaghettiish. With Urho3D I can create the UI with the Editor, save it as XML file and load it at runtime, subscribe to some events and it's done. It's even possible to combine several windows into one complex window. For example, the Options window consists of six windows: The container with just the tabs (taken from Urho3D-UI-Components) and each tab is a separate window. So far we have: a fully working Chat window with the different channels, a partly working Options window with fully customizeable shortcuts and multiple shortcuts per action, a Party window and Mission Map that's not working at all, a fully working Mail window and compose New Mail window (except that the multiline edit still bothers me a lot), a fully working Game menu, something that shows the Ping to the server and other things. Network Some details about the network layer. As mentioned earlier this is not a fast game, like an action game or a shooter. That's why I chose TCP over UDP. Using TCP takes out a lot of problems, like packet losses, wrong order of packets. With TCP, packets are always received in the right order, or something goes terribly wrong, e.g. disconnects. Of course this comes at a price (no advantage without disadvantage!), higher latency. But for slow games it may not matter so much. Update rate You know that interactive programs execute an endless loop. An interactive console program could look like this: void main() { bool running = true; while (running) { std::string input; std::getline(std::cin, input); if (input.compare("quit") == 0) running = false; else if ... } } A Windows program looks usually like this: void main() { MSG msg = { 0 }; while (msg.message != WM_QUIT) { if (::PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessageW(&msg); } } } A game isn't much different: void main() { while (the_game_is_running) { // Update game state Update(); // Render the frame Render(); // Wait to meet the desired frame rate. // If vertical synchronization is on, the Graphics API may do this. WaitSomeTime(); } } This game server does it similar, the games have an Update() method which is executed from time to time. The difference is that a game server does not update the game state in an endless loop and waits most of the time, but it uses a Scheduler. It would be a waste of time when it sleeps most of the time, it can simulate other games (or do something completely different). The game update method of this game server looks a bit like this (simplified): void Game::Update() { // Dispatcher Thread int64_t tick = Utils::AbTick(); if (lastUpdate_ == 0) lastUpdate_ = tick - NETWORK_TICK; uint32_t delta = static_cast<uint32_t>(tick - lastUpdate_); lastUpdate_ = tick; // First Update all objects for (const auto& o : objects_) { o->Update(delta); } // Send game status to players SendStatus(); // Schedule next update const int64_t end = Utils::AbTick(); const uint32_t duration = static_cast<uint32_t>(end - lastUpdate_); // At least SCHEDULER_MINTICKS const int32_t sleepTime = std::max<int32_t>(SCHEDULER_MINTICKS, NETWORK_TICK - duration); Asynch::Scheduler::Instance.Add( Asynch::CreateScheduledTask(sleepTime, std::bind(&Game::Update, this)) ); } The server runs the simulations every 50ms (NETWORK_TICK = 50), this are 20 simulations per second. The client runs updates every ~16ms (60FPS) or ~8ms (140FPS) or whatever frame rate it is running. The client sends all collected packets (e.g. player inputs) all 16ms (60 times per second) to the server, no matter if it runs at a higher frame rate (lower frame rates are a problem at the moment, that needs to be addressed...). The server collects all this inputs from the client and puts it into a queue, which is processed in the next update to calculate the next game state. Delta compression Delta compression means the server does not always send the whole game state to all clients, but only what has changed since the last state. This reduces bandwidth usage drastically. Since we use TCP we can assume that the client always knows the previous game state, so it's safe to send only the difference. This is the only compression it uses. The packets are small binary packets and may not compress well, so it's probably not worth the CPU cycles. Client/server asynchronicity There are mainly three methods to address the problem that client and server are asynchronous, which is caused by different update rates (20 updates/sec on server, 60 updates/sec on client), network latency, server load etc.: Entity interpolation is already done with Entity Position Interpolation. Input prediction is not yet done. Lag compensation/Server reconciliation will not be done. This is more important for fast games. Further reading In no particluar order. https://gafferongames.com/ http://ithare.com/mmog-world-states-and-reducing-traffic/ https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
  11. Player Replaced the ball with a real character model. At the moment I have just a few character models with two animations (run and idle): Video The character was made with MakeHuman and the animations are from Mixamo. The workflow is straight forward and (more or less) painless: In MakeHuman export the character as .mhx2. Import in Blender. The MakeHuman Blender Plugin has a MHX2 importer. If needed apply transformation, but if you use MHX2 i think this is not needed. Export from Blender as .fbx. Upload the FBX file to Mixamo. Select the animation. Download the FBX file. Import in Blender. Export the character with the Urho3D-Blender plugin. I would recommend to export a Prefab so you can load the whole thing with materials etc. at once. NPCs RPGs (and other games) usually have NPCs - non playing characters, well they are playing but they are computer controlled. This game should be largely scriptable. There are different game formats and maps and each should just differ in the script that is executed. A game script could look like this: function onStart() -- self is the this pointer -- Spawn an NPC and set the position. local smith = self:AddNpc("/scripts/creatures/npcs/smith.lua") if (smith ~= nil) then local x = -6.71275 local z = 12.5906 local y = self:GetTerrainHeight(x, z) smith:SetPosition(x, y, z) -- Here we just use the Y-axis, internally it uses Quaternions smith:SetRotation(180) end local merchant = self:AddNpc("/scripts/creatures/npcs/merchant.lua") if (merchant ~= nil) then local x = 4.92965 local z = 12.2049 local y = self:GetTerrainHeight(x, z) merchant:SetPosition(x, y, z) merchant:SetRotation(180) end end function onStop() end function onAddObject(object) print("Object added: " .. object:GetName()) end function onRemoveObject(object) print("Object removed: " .. object:GetName()) end function onPlayerJoin(player) player:AddEffect(empty, 1000, 0) print("Player joined: " .. player:GetName()) end function onPlayerLeave(player) player:RemoveEffect(1000) print("Player left: " .. player:GetName()) end -- Game Update function onUpdate(timeElapsed) -- print(timeElapsed) end As with other scripting APIs, there are events that are called by the program (from C++), and there are objects that have methods accessible by the script. An NPC script is as simple: -- Object stats/properties name = "Smith" level = 20 modelIndex = 5 -- Smith body model sex = 2 -- Male creatureState = 1 -- Idle prof1Index = 1 -- Warrior prof2Index = 0 -- None function onInit() return true end function onUpdate(timeElapsed) -- Do something intelligent! end -- self was selected by creature function onSelected(creature) print(creature:GetName() .. " selected me, the " .. self:GetName() .. " :D") end -- creature collides with self function onCollide(creature) -- Testing Octree query local objects = self:QueryObjects(2.0) print(type(objects)) for i, v in ipairs(objects) do print(i, v, v:GetName()) end end Navigation Navigation is a difficult topic. Fortunately there is Recast & Detour, a library to find paths with a navigation mesh. Currently it can to go to a static position and follow a moving object. Technically it's the same, but it doesn't recalculate the path when the object is not moving. However, I've read somewhere that Detour can calculate incomplete paths which would be useful for following objects, but I didn't figure that out yet. Video Detour uses navigation meshes created with Recast. The image bellow shows the generated navigation mesh based on the heightfield of this map. As mentioned earlier, the heightfield is just a bitmap where brighter colors are higher altitudes than darker colors. A mesh is created with a custom command line program from this bitmap, which Recast uses to generate the navigation mesh. To be continued...
  12. trill41


    A game server written in C++ from scratch. The game client uses Urho3D. Current Features Uses a single TCP stream for the game protocol. This is not a shooter or action game, more like a classical online RPG. Database back-end is currently MySQL (PostgresSQL and ODBC is also implemented). Instanced world. Encrypted Game and Login Protocol. Spawn any number of server which may have heavy load (game, file server) even on different hardware. Local (map), Guild chat and whisper is currently working, even across different game server. Static objects are directly loaded from Urho3D's scene files. Navigation using Recast/Detour. ETA In 100 years. Credits Server Asio Lua Kaguya Lua C++ Binding pugixml Recast & Detour Client Urho3D Asio Entity Position Interpolation Terrain I have been playing around with terrains and heightmaps. Creating heightmaps from bitmaps is very easy, color values basically correspond to altitude values. So you can generate an array with width * height elements with the height values, and with some simple calculations you get for every possible world position (x, z) the height (y). But at the moment it seems the server heightmap is slightly different to what Urho3D generates ;(: Video Finally this is fixed, the character sticks now exactly to the terrain. Cluster What we see here is a ABx server cluster. Since the server is built as a set of micro services it is easy to make a cluster. The screenshot shows three clients where one is connected to a different game server (Sun Shine) and whisper (blue) and guild (green) chat is still working (cross server chat). All the communication is done via TCP/IP so each server can be on different hardware. The login server is also some sort of load balancer since it redirects the game clients automatically to the game server with the least load. Data Server The Data server provides data from the database server and caches it. It also acts as thread-safe inter-server shared memory. There can be only one data server. It is the central point to which all other servers connect, and get their data from. This makes it possible to spawn any number of game server and they all share the same data. File Server The file server is a simple HTTP server providing files and other information. The client may connect to it from time to time and download data. There can be any number of file servers. Usually you may want to have file servers in different regions, and not on the same machine. A file server does not need much resources, just bandwidth. Login Server Used by the client to login, create accounts and manage characters. It also tells the client to which Game and File Server to connect. The client can query this server for available game server so it can connect "manually" to a certain game server. There can be only one login server, since all clients connects to this server. However, there is an optional TCP (Layer 4) load balancer/proxy server (ablb), which makes it possible to have several Login Servers. Once the client is authenticated, the connection to the login server is closed. Game Server The game server simulates the games. There can be any number of game servers, but if they run on the same machine, the game servers must listen on different ports. Since all game server connect to the same data server, all game server share the same data. Because this game is designed to have an instanced world, several game server instances appear to the player as one game server. It is even possible to change the game server with a simple menu click. Message Server This one is for inter server communication, for example to deliver messages from a player to another player on a different game server. It is also used to push notifications (e.g new mail) to the player.
  13. I still play Guild Wars (the original) every day.
  14. trill41

    What are you working on?

    Hi all, I'm new to the forum, but follow GameDev.net since a long time. Several times I tried to create a game, but I realized that I lack basic knowledge required for game development, especially 3D. This was the reason to begin with a basic 3D rendering engine. In the beginning it used OpenGL, but switched to D3D11 because I think it's easier. The screenshot shows that I still have some problems with textures, while some are working, others are not. Anyway, one time I'll fix it. The character was made with MakeHuman. Github Repo: https://github.com/stievie/Tiny3D All the best, and continue with your amazing projects.  
  15. Hi, thank you for your reply. You are right, I did not correctly initialize the vertex structure when loading the models. Initializing it fixes the problem. Thank you very much.
  • Advertisement

Important Information

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

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!