Announcement

Collapse
No announcement yet.

Networking Issue.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Networking Issue.

    Alright guys, I'm having an issue. I am trying to build entirely using blueprints(Can learn C++ but would rather not). This idea is going to be similar to an MMORPG, its going to be highly instanced in that most of the actual gameplay will take place in a location that has a maximum player count of 16 or 20. I need to develop some type of backend that interacts with SQL to store player data and item stats. I have a pretty good understanding of how blueprints work and coding is not a foreign object to me either, however my skill set so far encompasses python and only python. Could you set me down the pathway to achieve this?

    #2
    Originally posted by Hudolus View Post
    Alright guys, I'm having an issue. I am trying to build entirely using blueprints(Can learn C++ but would rather not). This idea is going to be similar to an MMORPG, its going to be highly instanced in that most of the actual gameplay will take place in a location that has a maximum player count of 16 or 20. I need to develop some type of backend that interacts with SQL to store player data and item stats. I have a pretty good understanding of how blueprints work and coding is not a foreign object to me either, however my skill set so far encompasses python and only python. Could you set me down the pathway to achieve this?
    Your client or dedicated server should not talk to a SQL server directly. Instead, you should build a backend server using HTTP (PHP/Python/Rails/.NET/etc.) or even something talking to a server in real time over a TCP connection. That backend server should talk to the database. If you choose the HTTP path and DON'T want to learn C++, there is a plugin called VaRest which allows you to deal with JSON in Blueprint.

    Comment


      #3
      I'm having trouble constructing my basic model for interaction. There is also no clear documentation of what functions are available to a user of that VaRest plugin. Some helpful souls over in the #Python channel over at freenode IRC said that to avoid conflicts my best bet would be to look into a JSON database and have my dedicated server talk to and store directly to it. I have no clue how the structure of a JSON database looks and how similar to SQL it is when pulling or storing records into it. They have stated that if I were to write a python program to listen to the JSON that it would require a massive amount of resources to interact with my suggested playerbase volume and there would be the risk of said JSON file hitting its max size before the python program saw the information and was able to store/confirm storage and remove it from the JSON to make room for more data. I am drowning here.

      Comment


        #4
        Originally posted by Hudolus View Post
        I'm having trouble constructing my basic model for interaction. There is also no clear documentation of what functions are available to a user of that VaRest plugin. Some helpful souls over in the #Python channel over at freenode IRC said that to avoid conflicts my best bet would be to look into a JSON database and have my dedicated server talk to and store directly to it. I have no clue how the structure of a JSON database looks and how similar to SQL it is when pulling or storing records into it. They have stated that if I were to write a python program to listen to the JSON that it would require a massive amount of resources to interact with my suggested playerbase volume and there would be the risk of said JSON file hitting its max size before the python program saw the information and was able to store/confirm storage and remove it from the JSON to make room for more data. I am drowning here.
        I think they were getting at using something like MongoDB which is designed as a document database and goes hand in hand with JSON and SQL is still fine too. Document databases and relational databases have pluses and minuses depending on what you want to achieve. You can also write JSON directly to a file on the hard disk the server is running on. It really depends what you want to do.

        If your game is not going to be persistent between servers then having flat JSON files could work and should be fairly lightweight. You can also directly talk to a NoSQL or SQL database in this case too and maybe possible with persistence if your dedicated server binaries are going to be private and all game servers are to be running on your own servers. However, if your dedicated server files are going to public and you do want persistence between servers you will want it to talk to a backend server first before hitting the database as the backend would authenticate connections and sanitise the input data.

        Comment


          #5
          I do want my game to be persistent between servers, but according to MongoDB's site JSON files are capped at 16mb and I'm more than positive with all of the data I need to store I will exceed that. Unless MongoDB can chain the JSON files together so say, player logs in game needs to pull his character model info, character name, equipment info, health, abilities. Thats a lot of data per character to store/recall and it all has to be stored server side. So if I can store those things and MongoDB can sort out those requests. I've never dealt with an issue like this, it's a tad overwhelming due to the fact that JSON files are outside my scope of knowledge so I don't know alot about how to interact with them. As well as UE4 is new to me so learning how I can get data OUT of the dedicated server has been a venture as well.

          Comment


            #6
            Originally posted by Hudolus View Post
            I do want my game to be persistent between servers, but according to MongoDB's site JSON files are capped at 16mb and I'm more than positive with all of the data I need to store I will exceed that. Unless MongoDB can chain the JSON files together so say, player logs in game needs to pull his character model info, character name, equipment info, health, abilities. Thats a lot of data per character to store/recall and it all has to be stored server side. So if I can store those things and MongoDB can sort out those requests. I've never dealt with an issue like this, it's a tad overwhelming due to the fact that JSON files are outside my scope of knowledge so I don't know alot about how to interact with them. As well as UE4 is new to me so learning how I can get data OUT of the dedicated server has been a venture as well.
            Where does it say that on MongoDB's site? Perhaps it's a 16MB limit per-record and a record for an individual player is not going to take up anywhere near that much space.

            Comment


              #7
              Yes its 16MB per record, but I still fail to see how I'm going accomplish my goal of storing/retrieving player information with VaRest/MongoDB. The two would require a bridge of some sort to create the interaction between server/DB. Why would I not want my dedicated server to communicate directly to a DB again? If you could walk me through the process of creating a .cpp file that held my SQL connection info, and then creating a blueprint that I would elevate to a server execution only blueprint. I could cause the server to initiate a connection to the SQL server and then walk me through creating some basic blueprints for pulling data from a server based on a 1-3 variables, I could very easily accomplish my goals with that. If its possible with VaRest/MongoDB and I'm just missing the point please explain it to me, I probably am just missing the capability. I understand they both work off of JSON files but MongoDB's role as far as I understand is, he just stores JSON files and then just like other database applications you can query to pull specific json files. So while the VaRest would be able to write JSON files that a middleman application could have MongoDB store, we have no way of querying MongoDB to pull the specific json file and then have VaRest switch to that particular JSON file and deposit the information needed. VaRest is a great plugin but it lacks the power of accessing/using a large amount of data. It is limited to a externally updated JSON file. While it can make changes to that JSON file it would require an extreme amount of effort to design and utilize an application to work around VaRests shortcomings. I really appreciate how quickly you've been replying to me and how helpful you've been to me. I know my knowledge is quite limited and I can't explain things very well. Hopefully you will continue to work with me until we approach a resolution!

              Comment


                #8
                Originally posted by Hudolus View Post
                Yes its 16MB per record, but I still fail to see how I'm going accomplish my goal of storing/retrieving player information with VaRest/MongoDB. The two would require a bridge of some sort to create the interaction between server/DB. Why would I not want my dedicated server to communicate directly to a DB again? If you could walk me through the process of creating a .cpp file that held my SQL connection info, and then creating a blueprint that I would elevate to a server execution only blueprint. I could cause the server to initiate a connection to the SQL server and then walk me through creating some basic blueprints for pulling data from a server based on a 1-3 variables, I could very easily accomplish my goals with that. If its possible with VaRest/MongoDB and I'm just missing the point please explain it to me, I probably am just missing the capability. I understand they both work off of JSON files but MongoDB's role as far as I understand is, he just stores JSON files and then just like other database applications you can query to pull specific json files. So while the VaRest would be able to write JSON files that a middleman application could have MongoDB store, we have no way of querying MongoDB to pull the specific json file and then have VaRest switch to that particular JSON file and deposit the information needed. VaRest is a great plugin but it lacks the power of accessing/using a large amount of data. It is limited to a externally updated JSON file. While it can make changes to that JSON file it would require an extreme amount of effort to design and utilize an application to work around VaRests shortcomings. I really appreciate how quickly you've been replying to me and how helpful you've been to me. I know my knowledge is quite limited and I can't explain things very well. Hopefully you will continue to work with me until we approach a resolution!
                You don't want the game talking directly to a database (especially one you don't control) for security reasons. There are plenty of things that can go wrong when you do that, just ask Edmund McMillen.

                A RESTful HTTP API that serves JSON is how you'd go about it. There are many solutions for pretty much every web development platform on the planet that'll allow you to achieve that.

                Comment


                  #9
                  If you Include Http.h you can use HTTPRequests. You only need to write php scripts that interact with your Database.
                  You can POST requests with over HTTP inside your Project. The POST Data can be a JSON String.
                  In your php Script you can echo the Query result as a JSON too.

                  That's how i made a login system. I also made a script that refreshes sessions every minute and is called by a Timer inside my level Blueprint.
                  But i moved over to Steamworks, since i don't need a complete login system and servers to save inventorys. I only use the local
                  savestates for saving maps and inventorys so i haven't finished the HTTPRequest thing.

                  But i guess you could work with it.
                  Open for contracted work | C++/BP (incl. Multiplayer) | Tutoring | VR

                  My UE4 Blog/Page with Tutorials and more: Hit me for ALL the things!
                  (Including 100+ Pages Multiplayer Network Compendium to get you started.)

                  Comment


                    #10
                    Originally posted by sswires View Post
                    You don't want the game talking directly to a database (especially one you don't control) for security reasons. There are plenty of things that can go wrong when you do that, just ask Edmund McMillen.

                    A RESTful HTTP API that serves JSON is how you'd go about it. There are many solutions for pretty much every web development platform on the planet that'll allow you to achieve that.
                    So your suggestion in short, go learn about RESTful HTTP API's that serve JSON and use PHP or Pythong to build your backend. So here's what I've got for my model: Anything involving changing a skill or piece of gear is a direct connection between client and REST enabled webserver. While anything involving movement, combat or environment interaction takes place between webserver and dedicated server and eventually client but all data exchanged for combat calculations is between webserver and dedicated server. Would that work?
                    Last edited by Hudolus; 09-08-2014, 12:07 PM.

                    Comment


                      #11
                      Originally posted by Hudolus View Post
                      So your suggestion in short, go learn about RESTful HTTP API's that serve JSON and use PHP or Pythong to build your backend. So here's what I've got for my model: Anything involving changing a skill or piece of gear is a direct connection between client and REST enabled webserver. While anything involving movement, combat or environment interaction takes place between webserver and dedicated server and eventually client but all data exchanged for combat calculations is between webserver and dedicated server. Would that work?
                      I'm not sure about the idea of the web server being responsible for combat calculations, is there a reason your game's dedicated server couldn't do that? Storing stats and inventory at intervals or on certain events (eg. disconnect) is fairly lightweight but for something that will be done constantly in-game HTTP might not be the best way to go. If that's the case you'll have to look at using something more real time by having a central server that your game's dedicated server connects to that has a persistent connection and can send and receive data with low overhead. If that's a route you want to take then you'll have to look at sockets programming and using serialisation libraries like Protobuf and Apache Thrift.

                      Comment


                        #12
                        Originally posted by sswires View Post
                        I'm not sure about the idea of the web server being responsible for combat calculations, is there a reason your game's dedicated server couldn't do that? Storing stats and inventory at intervals or on certain events (eg. disconnect) is fairly lightweight but for something that will be done constantly in-game HTTP might not be the best way to go. If that's the case you'll have to look at using something more real time by having a central server that your game's dedicated server connects to that has a persistent connection and can send and receive data with low overhead. If that's a route you want to take then you'll have to look at sockets programming and using serialisation libraries like Protobuf and Apache Thrift.
                        The other person who commented earlier said

                        Originally posted by eXi View Post
                        If you Include Http.h you can use HTTPRequests. You only need to write php scripts that interact with your Database.
                        You can POST requests with over HTTP inside your Project. The POST Data can be a JSON String.
                        In your php Script you can echo the Query result as a JSON too.

                        That's how i made a login system. I also made a script that refreshes sessions every minute and is called by a Timer inside my level Blueprint.
                        But i moved over to Steamworks, since i don't need a complete login system and servers to save inventorys. I only use the local
                        savestates for saving maps and inventorys so i haven't finished the HTTPRequest thing.

                        But i guess you could work with it.
                        Okay, could you point me in the right direction of a specific language and some source of information to get started?

                        Comment


                          #13
                          Yes,

                          i hope i find everything i needed for this. First you need to add Http to your Dependency.

                          You can do this inside your Build file. "YOURPROJECT.Build.cs" and yes, this file is C#, but that's not that hard.
                          You should find a line like this:

                          Code:
                          PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Http" });
                          But without the "Http". Just add it.

                          Now you create a simple Code for you project. For example with the Actor Parent class.
                          Now include the "Http.h" header file. I found it here:

                          Code:
                          #include "Runtime/Online/HTTP/Public/Http.h"
                          There are possibilities to shorten the path, but i'm not that skilled. You can probably look up Ramas SteamNetwork Guide to
                          copy the lines for shortening the Include paths.

                          Now you need to create at least 2 functions inside your Header file (the one of the new Class you have created).

                          It should be structured like this:

                          Code:
                          void LoginRequest(FString PostData);
                          void OnLoginRequestComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
                          For each different request function, you would need to make an additional 2 functions.

                          The first one is the request, the second one is a delegate that is called after your request (at least i hope that it's like that,
                          but you will still understand what i mean).

                          Now inside your .cpp file, you would need to include Json.h too, to use Json string functions.

                          The first function "LoginRequest(FString PostData)" should look something like this:

                          Code:
                          void AHTTP_LoginAndID::LoginRequest(FString PostData)
                          {
                          	TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
                          	HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
                          	HttpRequest->SetURL(TEXT("http://127.0.0.1/gamelogin.php"));
                          	HttpRequest->SetVerb(TEXT("POST"));
                          	HttpRequest->SetContentAsString(PostData);
                          	HttpRequest->OnProcessRequestComplete().BindUObject(this, &AHTTP_LoginAndID::OnLoginRequestComplete);
                          
                          	if (!HttpRequest->ProcessRequest())
                          	{
                          		GEngine->AddOnScreenDebugMessage(1, 600.0f, FColor::Green, TEXT("Request failed at start!"));
                          	}
                          
                          }
                          The URL, for example, is the path to your Webserver and the matching php script.
                          The Method you use is "POST" because you POST information to the script.
                          The BinUObject is the Delegate. It's the second function you created. You bind it to the Request event.

                          The IF Clause is something i made. You don't have to use the AddOnScreenDebugMessage.

                          Your FString is the Data you want to sent. You can use Json Strings here.

                          The Delegate looks something like this:

                          Code:
                          void AHTTP_LoginAndID::OnLoginRequestComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
                          {
                          	ASurvivalCharacter* MyCharacter;
                          	FString MessageBody = "";
                          	if (!Response.IsValid())
                          	{
                          		MessageBody = "{\"success\":\"Error: Unable to process HTTP Request!\"}";
                          		GEngine->AddOnScreenDebugMessage(1, 600.0f, FColor::Green, MessageBody);
                          	}
                          	else if (EHttpResponseCodes::IsOk(Response->GetResponseCode()))
                          	{
                          		MessageBody = Response->GetContentAsString();
                          		GEngine->AddOnScreenDebugMessage(1, 600.0f, FColor::Green, MessageBody);
                          		// Cast the found AActor to ASurvivalCharacter
                          		MyCharacter = (ASurvivalCharacter*)UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);
                          
                          		MyCharacter->AccountID = FCString::Atoi(*MessageBody);
                          
                          		/* JSON VERSION
                          		FString JsonRaw = Response->GetContentAsString();
                          		TSharedPtr<FJsonObject> JsonParsed;
                          		TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonRaw);
                          		if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
                          		{
                          		MessageBody = JsonParsed->GetStringField("id");
                          		}
                          		*/
                          	}
                          	else
                          	{
                          		MessageBody = FString::Printf(TEXT("{\"success\":\"HTTP Error: %d\"}"), Response->GetResponseCode());
                          
                          	}
                          }
                          This is just copied from my test project, so you would need to change the ClassName and some other things.
                          What i'm doing here is the following:

                          I check the Response. First if it is valid and second if the ResponseCode is ok.
                          If both is ok, than we can use the Response. "GetContentAsString", for example,
                          returns the String that you send back as an echo inside your php script.

                          In my case, it is a unique userid. I display it to check if everything is working and save it to my character.

                          The commented section with "JSON VERSION" as title was just a test to deserialize a Json string that was echod by a php script.

                          You can make multiple functions like this, to Request different things and make them BlueprintCallable to use them in BPs

                          (: Hope that helps.
                          Last edited by eXi; 09-12-2014, 06:09 AM.
                          Open for contracted work | C++/BP (incl. Multiplayer) | Tutoring | VR

                          My UE4 Blog/Page with Tutorials and more: Hit me for ALL the things!
                          (Including 100+ Pages Multiplayer Network Compendium to get you started.)

                          Comment


                            #14
                            Wow, mysql_query, really? You know that's been deprecated for the longest time and you should use mysqli or PDO instead. Is that also vulnerable to SQL injection too? Also you shouldn't use local files or Steam's cloud saving functionality to save persistent data about a player as that can easily be cheated.

                            Comment


                              #15
                              Originally posted by Hudolus View Post
                              The other person who commented earlier said


                              Okay, could you point me in the right direction of a specific language and some source of information to get started?
                              That point me in the right direction was directed at sswires. Can I use Python to write a winsocket backend? What do I need to do where should I start?

                              Comment

                              Working...
                              X