User Tag List

Page 1 of 3 123 LastLast
Results 1 to 40 of 99

Thread: [Plugin] Socket.io Client

  1. #1
    1

    [Plugin] Socket.io Client

    Socket.io is a performant real-time bi-directional communication library. There are two parts, the server written in node.js and the client typically javascript for the web. There are alternative client implementations and I've used the C++ client library and ported it to UE4.

    For the London is Unreal meetup I made a presentation on the topic of plugins and chose to implement a useful plugin live during the presentation. A socket.io client was chosen as the plugin, which was finished with a basic Connect, Bind, Emit functions and an On event all interfaced through an Actor Component.

    Since 0.4, the plugin is pretty feature complete, let me know what other features you think are missing!

    Contribute
    Currently missing static libs for various platforms see https://github.com/getnamo/socketio-client-ue4/issues

    Download


    Resources
    Github Repository - Always contains the latest documentation
    Example UMG Chat Project (contains server and both web and ue4 client)
    How to connect Unreal Engine 4 to local server via WebSocket using blueprints? - By Egor Bogomyakov

    Example project is a functional UMG based chat window place in world showing real-time communication ability of UE4 -> Web/Mobile


    Quick Install & Setup

    1. Download Latest Release
    2. Create new or choose project.
    3. Browse to your project folder (typically found at Documents/Unreal Project/{Your Project Root})
    4. Copy *Plugins* folder into your Project root.
    5. Restart the Editor and open your project again. Plugin is now ready to use.


    How to use - BP Basics

    Add the SocketIO Client Component to your blueprint actor of choice



    Specify your address and port, defaults to localhost (127.0.0.1) at port 3000. Note that since 0.2.0 connect is optional as the component will auto connect unless you disable autoconnect via boolean.



    Call bind for each event you wish the client to subscribe, e.g. 'chat message'. If you expect to receive events, select your component and in the Details pane press the + to add an 'OnEvent' event to your event graph.

    Handle this event for your event types, e.g. printing 'chat message' event strings.



    If you want to send information to the server, emit events on the SocketIO Client Component, e.g. pressing M to emit a 'chat message' string



    Changelist

    0.6.0
    -Rebased to accomodate #43. You can now put FSocketIONative anywhere with your own allocation structure.
    -'On' event dispatch changed to 'OnEvent'.
    -Candidate fixes for #41, #32, and #38
    -Fixes to underlying library stopping re connection attempts when you close a connection: getnamo/socket.io-client-cpp@3f0cd99

    0.5.2
    -Fixed boolean always returning false #35

    0.5.1
    -Fixed undefined as second emit parameter from server #36

    0.5.0
    -Fixes for disconnecting while communicating with an unreachable server #32
    -Boost updated to 1.62
    -Socket.io-cpp updated to latest master merge
    -misc internal features for tracking and killing lambda threads

    0.4.8
    -UTF8 Support
    -Connection fixes
    -Session ID fix
    -Compile fixes for IWYU changes in 4.15
    -Scaffolds for other platforms from contributors (non-functioning)

    0.4.0
    -Added SIOJson for Blueprint Json construction and conversion, based on VaRest
    -Auto-conversion for nodes
    -Blueprint callbacks and events bound to functions references by function name
    -Conversion of JsonObjects to and from UStructs, including Blueprint UStructs with automatically trimmed long names into readable short names
    -Overloaded EmitNative for all expect UE native data types
    -Much simplified C++ usage based on FJsonValue and FJsonObject including nested binary support (hackery!)
    -and much more

    0.2.6-0.3.4
    -Internal versions for 0.4.0

    0.2.5
    -Change event names and signatures
    -Add wider support for raw message emitting and receiving

    0.2.2-0.2.4
    -raw sio::message support and events

    0.2.1
    -added proper binary send/receive support
    -added functioning onconnect/disconnect events, no longer require
    special events on your server
    -added on namespace connect/disconnect events
    -added on fail event

    0.2.0
    -Update to 4.13
    -Added connect/disconnect signatures (these have to be implemented by
    the server if used)
    -Added C++ lambda binds do e.g.
    BindDataLambdaToEvent([&](const FString& EventName, const FString& EventData) { //your code }, Name, Namespace);
    to use it
    -Bind changed name to BindEvent
    -Added Namespace support
    -Connection runs on background thread (should not be blocking anymore)

    0.1.2
    -Updated compiled dlls and version for 4.12 (no code changes)

    0.1.1
    -First release
    Last edited by getnamo; 05-07-2017 at 02:47 PM.

  2. #2
    0
    Presentation slides? >

  3. #3
    0
    Quote Originally Posted by Zarkopafilis View Post
    Presentation slides? >
    Presentation didn't have too much technical meat before the actual demo as I did the whole thing live but here are the slides:
    https://docs.google.com/presentation/d/1QhaEAWNkXeEr7NMvB7ilYcTSNjtZ7GwmVaHPiIXxcyw/edit?usp=sharing

    And the video shown for the example custom c++ function is found here:
    https://www.youtube.com/watch?v=4CgCJsThsWU
    Last edited by getnamo; 05-14-2016 at 07:10 AM.

  4. #4
    0
    What can I say? Bookmarked :P

  5. #5
    1
    Thanks Getnamo, really enjoyed your daring live c++ coding demo - glad it wasn't me. Going to take a proper look at this next week. I'm quite interested in linking libraries so if you've got any pointers about that I'd be very interested.

  6. #6
    0
    Quote Originally Posted by getnamo View Post
    Socket.io is a performant real-time bi-directional communication library. There are two parts, the server written in node.js and the client typically javascript for the web. There are alternative client implementations and I've used the C++ client library and ported it to UE4.

    For the London is Unreal meetup I made a presentation on the topic of plugins and chose to implement a useful plugin live during the presentation. A socket.io client was chosen as the plugin, which was finished with a basic Connect, Bind, Emit functions and an On event all interfaced through an Actor Component.

    For now this is a basic bind, but may be extended in the future with better documentation. Enjoy!

    Download
    Latest

    Resources
    Github Repository
    Example UMG Chat Project (contains server and both web and ue4 client)

    Example project is a functional UMG based chat window place in world showing real-time communication ability of UE4 -> Web/Mobile
    Looks like a plugin I need to add to my tutorial... That is really neat!

    teak
    "A little bit of nonsense now and then is cherished by the wisest men..."
    -- Willy Wonka

    twitter: @teak421 -- Smooth Zoom Camera Plugin for 4.14+: here.
    Source Build with Optional Plugin Tutorial: here.

  7. #7
    0
    Added some basic BP instructions to both the github readme and for convenience, this thread. Going forward the github readme will have all the most up to date documentation.

  8. #8
    0
    Great work!

    Going to give this 1 a try for some User detail input for an event I have coming up, should save me some time compared to doing REST server!

  9. #9
    0
    Infiltrator
    Join Date
    Feb 2016
    Posts
    22
    Any plans for updating this for 4.12?
    I'm currently working on a project in 4.12 and could really use this.

    Thanks!

  10. #10
    0
    Quote Originally Posted by sjespers View Post
    Any plans for updating this for 4.12?
    I'm currently working on a project in 4.12 and could really use this.

    Thanks!
    Always nice to see someone using this ! Please do note that the current bind is functional albeit a bit simple since it was done in 30min during the presentation and could use some updates to make event binding a bit easier.

    Update to 0.1.2
    -Updated compiled dlls and versioning for 4.12 (no code changes)

    Grab the latest at the usual spot: https://github.com/getnamo/socketio-client-ue4/releases
    Last edited by getnamo; 06-16-2016 at 03:40 PM.

  11. #11
    0
    @getnamo Thanks for this awesome socketio client, works well.

    but I am not able to use it in executable, it is working when I play in the editor, but when try to Launch as HTML5, Launch Fails.
    When I turn off the plugin and then launch project as HTML5, it works.

    Is there anything with the compilation? How to use it in executable? Please reply.

  12. #12
    0
    Quote Originally Posted by DIVYA ADITYA View Post
    @getnamo Thanks for this awesome socketio client, works well.

    but I am not able to use it in executable, it is working when I play in the editor, but when try to Launch as HTML5, Launch Fails.
    When I turn off the plugin and then launch project as HTML5, it works.

    Is there anything with the compilation? How to use it in executable? Please reply.
    The boost and socket.io static libraries that this plugin depends on have only been compiled for the Win32 and Win64 platforms. I'm unsure how plugin dependencies are handled for the ue4 html5 platform as it is not one I develop for and the documentation and questions on building with plugins are scarce and without resolution.

    Perhaps someone from epic would be able to chime in on what steps would be required to include static libs for the ue html5 platform?

  13. #13
    0
    First, awesome work! And they are really clean to use from Blueprints. I do have one quick question though. I have a node server that I have been using as the backend for Unity and am looking to test it out against UE4, which there wasn't a client for socket.io when I first looked, so this is awesome!

    The issue I am running into is if I pass a JSON object instead of a string, I dont seem to get anything back from the plugin. Are there plans to support more advanced objects?

    Thanks!

    Edit: Adding screenshot, unless I call JSON.stringify on my objects this always goes to empty string

    Name:  json.png
Views: 3445
Size:  78.1 KB
    Last edited by bot2600; 07-10-2016 at 07:45 PM. Reason: Added Blueprint

  14. #14
    0
    Ok, one last issue I found, I might go look at the source and see if the 3rd party library is exposing it and it just needs to be wrapped or if it isn't there.

    It looks like the client hears socket.emit but doesnt hear io.emit. Let me see if I can explain that better. On the javascript side there are events that are inside of your existing connection, and those are what I am considering socket.emit, then there are those that are server level that run in the game loop. They fire irregardless of your connection being present or not, though of course I suppress them when noone is connected

    Anyhow, awesome start! If I get time I will poke around at it and do a PR if it is something easy to fix but my C++ is limited at best

    Edit: Sorry, just re-read the first message and noticed you stated this was very basic. Sorry for being silly
    Last edited by bot2600; 07-11-2016 at 12:39 AM. Reason: Silliness

  15. #15
    0
    Quote Originally Posted by bot2600 View Post
    First, awesome work! And they are really clean to use from Blueprints. I do have one quick question though. I have a node server that I have been using as the backend for Unity and am looking to test it out against UE4, which there wasn't a client for socket.io when I first looked, so this is awesome!

    The issue I am running into is if I pass a JSON object instead of a string, I dont seem to get anything back from the plugin. Are there plans to support more advanced objects?

    Thanks!

    Edit: Adding screenshot, unless I call JSON.stringify on my objects this always goes to empty string

    ...
    Excellent idea on adding JSON parsing. When I bound the function, due to time constraints and simplicity I do a data->get_string() then convert to UE FString to get a message, seen here: https://github.com/getnamo/socketio-client-ue4/blob/master/Source/SocketIOClient/Private/SocketIOClientComponent.cpp#L41

    The base library that I integrated uses sio::message as wrapper for JSON objects. This needs to take the received message object and turn it into a JSON string so you can parse it using the blueprint utility you're using. Off the top of my head I thought get_string() would do that, but apparently it strictly checks for 'string' type variables. Looking in the socket.io-client-cpp library source would be the best place to spot how.


    Edit: seems the library doesn't natively support message<->JSON conversion, but a workaround can be found here: https://github.com/socketio/socket.io-client-cpp/issues/87. To add the workaround to the plugin would require adding that function to the component implementation and just call it if we get an empty string from our regular method.

    Quote Originally Posted by bot2600 View Post
    Ok, one last issue I found, I might go look at the source and see if the 3rd party library is exposing it and it just needs to be wrapped or if it isn't there.

    It looks like the client hears socket.emit but doesnt hear io.emit. Let me see if I can explain that better. On the javascript side there are events that are inside of your existing connection, and those are what I am considering socket.emit, then there are those that are server level that run in the game loop. They fire irregardless of your connection being present or not, though of course I suppress them when noone is connected

    Anyhow, awesome start! If I get time I will poke around at it and do a PR if it is something easy to fix but my C++ is limited at best

    Edit: Sorry, just re-read the first message and noticed you stated this was very basic. Sorry for being silly
    Have you tried io.sockets.emit()? This should work IMO, but it may be down to listening to the broadcast correctly.

    I've added the two issues here: https://github.com/getnamo/socketio-client-ue4/issues and this is the link to the underlying library: https://github.com/socketio/socket.io-client-cpp let me know what you discover!
    Last edited by getnamo; 07-11-2016 at 10:40 AM.

  16. #16
    0
    Yes, I poked around a bit at the interface for the base library you used, didn't even realize the source is out there, that will make things easier. I'll have to take a look at what it takes to compile a plugin this weekend and see if I can get some more functionality going. Returning the object instead of a string would have actually been more convenient anyhow as I could do just about anything with it once I had that! I did see the base library has that and other magic that can come out.

    For the io.sockets.emit(), I think its the same thing, io.emit emits to all active socket connections, but I will take a look and see. I am at work now so I don't have the notes I took when I looked at the base library unfortunately.

    Thanks for the response, sorry for stirring everything up on something that was basically just a prototype

  17. #17
    0
    Infiltrator
    Join Date
    Jan 2016
    Posts
    11
    Hello, first of all thank you very much for your plugin, it's been very useful to me
    Similarly to DIVYA ADITYA, I needed to use this plugin for another platform (Android), and I was trying to recompile your source code for using it as an Android library (I was going to make you a pull request once I had it all builted and tested, if you might be interested ). However, I am having several issues even to compile your code and its dependencies. VS2015 for UE4 does't seem to like websocketpp and boost as dependencies. Did you have to do some particular trick, in order to compile your library with those dependencies?

  18. #18
    0
    Quote Originally Posted by ocramot View Post
    Hello, first of all thank you very much for your plugin, it's been very useful to me
    Similarly to DIVYA ADITYA, I needed to use this plugin for another platform (Android), and I was trying to recompile your source code for using it as an Android library (I was going to make you a pull request once I had it all builted and tested, if you might be interested ). However, I am having several issues even to compile your code and its dependencies. VS2015 for UE4 does't seem to like websocketpp and boost as dependencies. Did you have to do some particular trick, in order to compile your library with those dependencies?
    Yeah the original library source is at https://github.com/socketio/socket.io-client-cpp. If I remember right I had to download boost 1.6 and compile it and then grab https://github.com/zaphoyd/websocketpp/network one of the forks in websocketpp that solved some of the compile issues there. Instead of just adding the prebuilt libraries in the repo, maybe I should find the old source for building those libraries for vs2015, I'll dig around!

    If you do get a successful android build, by all means make pull requests! This is a community plugin, not something exclusive.

  19. #19
    0
    Downloaded and I plan on experimenting with your plugin in a little test project. Time to dive back into learning Socket.io and Nodejs!

  20. #20
    0
    @getnamo so I found out if the server is unavailable (crashed), the editor completely freezes up and I have to end it.

  21. #21
    0
    Quote Originally Posted by DatapawWolf View Post
    @getnamo so I found out if the server is unavailable (crashed), the editor completely freezes up and I have to end it.
    Interesting that sounds like the timeout happens on the game thread, the solution is to simply make the connection attempt off-thread. I've added it to issues: https://github.com/getnamo/socketio-client-ue4/issues/3 and will try to address it next time I make a pass on the plugin. Feel free to make pull requests if you fix it before

  22. #22
    0
    Hi,
    thanks for the plugin. It seems I have some trouble getting it to work though. I use the version for UE4.11, socketIO is running on 0.9. I try to connect to socket io with connect node "http://192.168.1.50:5000" then I want to emit a command. The colleague who set up the Server said SocketIO Namespace was "events" and the event I need to send to is called "unityFanSpeedEvent" and receives only a number between 0 and 100.

    I guess the problem is the SocketIO namespace, I'm not sure in what node I need to add the namespace (connect or emit?). Sorry if this is some kind of a stupid question, it's my first time working with socketIO.

    Here is what I'm trying to do:
    Name:  ue4SocketIO.PNG
Views: 2963
Size:  28.2 KB

  23. #23
    0
    Quote Originally Posted by Tyleet View Post
    Hi,
    thanks for the plugin. It seems I have some trouble getting it to work though. I use the version for UE4.11, socketIO is running on 0.9. I try to connect to socket io with connect node "http://192.168.1.50:5000" then I want to emit a command. The colleague who set up the Server said SocketIO Namespace was "events" and the event I need to send to is called "unityFanSpeedEvent" and receives only a number between 0 and 100.

    I guess the problem is the SocketIO namespace, I'm not sure in what node I need to add the namespace (connect or emit?). Sorry if this is some kind of a stupid question, it's my first time working with socketIO.

    Here is what I'm trying to do:
    ...
    So the current plugin is very bare bones, in terms of actual binding meat it's only 40-50 lines of code, enough to have been done in a short presentation as a proof of concept:

    Code:
    #include "SocketIOClientPrivatePCH.h"
    #include "SocketIOClientComponent.h"
    
    
    USocketIOClientComponent::USocketIOClientComponent(const FObjectInitializer &init) : UActorComponent(init)
    {
    	bWantsInitializeComponent = true;
    	bAutoActivate = true;
    }
    
    std::string StdString(FString UEString)
    {
    	return std::string(TCHAR_TO_UTF8(*UEString));
    }
    FString FStringFromStd(std::string StdString)
    {
    	return FString(StdString.c_str());
    }
    
    
    void USocketIOClientComponent::Connect(FString AddressAndPort)
    {
    	if (!AddressAndPort.IsEmpty())
    	{
    		PrivateClient.connect(StdString(AddressAndPort));
    	}
    	else
    	{
    		PrivateClient.connect("http://localhost:3000");
    	}
    }
    
    void USocketIOClientComponent::Emit(FString Name, FString Data)
    {
    	PrivateClient.socket()->emit(StdString(Name), StdString(Data));
    	//UE_LOG(LogTemp, Log, TEXT("Emit %s with %s"), *Name, *Data);
    }
    
    void USocketIOClientComponent::Bind(FString Name)
    {
    	PrivateClient.socket()->on(StdString(Name), sio::socket::event_listener_aux([&](std::string const& name, sio::message::ptr const& data, bool isAck, sio::message::list &ack_resp) {
    
    		const FString SafeName = FStringFromStd(name);
    		const FString SafeData = FStringFromStd(data->get_string());
    		FFunctionGraphTask::CreateAndDispatchWhenReady([&, SafeName, SafeData]
    		{
    			On.Broadcast(SafeName, SafeData);
    		}, TStatId(), nullptr, ENamedThreads::GameThread);
    	}));
    }
    That is literally it. But it's apparently useful, so I may have to look into extending it a bit

    It should be a fairly easy modification to support namespaces. The current code uses

    Code:
    PrivateClient.socket()-> ...
    which fetches the default namespace "/" and the method should just expand to add a namespace variable e.g.

    Code:
    FString Namespace = FString(TEXT("events"));
    PrivateClient.socket(StdString(Namespace))-> ...
    events.

    Feel free to modify the source and make a pull request, otherwise it may take a bit of time before I make a pass on the plugin with the fixes. I've added a note about it in github issues on the repo.

  24. #24
    0
    Hi,
    thanks for the quick reply, I will try that and let you know the results.

  25. #25
    0
    EDIT: I just tested my theory that it is an socketIO version problem since the legacy server is running 0.9. Set up some local servers on my pc one with 1.x and one for 0.9, 0.9 only throws warnings when Unreal tries to connect, 1.x accepts the connection.


    Quote Originally Posted by getnamo View Post
    So the current plugin is very bare bones, in terms of actual binding meat it's only 40-50 lines of code, enough to have been done in a short presentation as a proof of concept:

    Code:
    #include "SocketIOClientPrivatePCH.h"
    #include "SocketIOClientComponent.h"
    
    
    USocketIOClientComponent::USocketIOClientComponent(const FObjectInitializer &init) : UActorComponent(init)
    {
    	bWantsInitializeComponent = true;
    	bAutoActivate = true;
    }
    
    std::string StdString(FString UEString)
    {
    	return std::string(TCHAR_TO_UTF8(*UEString));
    }
    FString FStringFromStd(std::string StdString)
    {
    	return FString(StdString.c_str());
    }
    
    
    void USocketIOClientComponent::Connect(FString AddressAndPort)
    {
    	if (!AddressAndPort.IsEmpty())
    	{
    		PrivateClient.connect(StdString(AddressAndPort));
    	}
    	else
    	{
    		PrivateClient.connect("http://localhost:3000");
    	}
    }
    
    void USocketIOClientComponent::Emit(FString Name, FString Data)
    {
    	PrivateClient.socket()->emit(StdString(Name), StdString(Data));
    	//UE_LOG(LogTemp, Log, TEXT("Emit %s with %s"), *Name, *Data);
    }
    
    void USocketIOClientComponent::Bind(FString Name)
    {
    	PrivateClient.socket()->on(StdString(Name), sio::socket::event_listener_aux([&](std::string const& name, sio::message::ptr const& data, bool isAck, sio::message::list &ack_resp) {
    
    		const FString SafeName = FStringFromStd(name);
    		const FString SafeData = FStringFromStd(data->get_string());
    		FFunctionGraphTask::CreateAndDispatchWhenReady([&, SafeName, SafeData]
    		{
    			On.Broadcast(SafeName, SafeData);
    		}, TStatId(), nullptr, ENamedThreads::GameThread);
    	}));
    }
    That is literally it. But it's apparently useful, so I may have to look into extending it a bit

    It should be a fairly easy modification to support namespaces. The current code uses

    Code:
    PrivateClient.socket()-> ...
    which fetches the default namespace "/" and the method should just expand to add a namespace variable e.g.

    Code:
    FString Namespace = FString(TEXT("events"));
    PrivateClient.socket(StdString(Namespace))-> ...
    events.

    Feel free to modify the source and make a pull request, otherwise it may take a bit of time before I make a pass on the plugin with the fixes. I've added a note about it in github issues on the repo.
    Hi,
    so I tried modifying your source code, but it seems I can't get it to run. Even if I hardcode IP, namespace, eventname and data into the source nothing gets through to the server.

    Code:
    void USocketIOClientComponent::Connect(FString AddressAndPort, FString nSpace)
    {
    	if (!AddressAndPort.IsEmpty())
    	{
    		Namespace = nSpace;
    		PrivateClient.connect("http://192.168.1.50:5000");//StdString(AddressAndPort));
    		UE_LOG(LogTemp, Log, TEXT("%s"), *nSpace);
    		
    	}
    ...
    
    void USocketIOClientComponent::Emit(FString Name, FString Data)
    {
    	FString speed = FString(TEXT("100"));
    	FString nsp = FString(TEXT("/events"));
    	FString eve = FString(TEXT("unityFanSpeedEvent"));
    	PrivateClient.socket(StdString(nsp))->emit(StdString(eve),StdString(speed));
    	//PrivateClient.socket("/servo"/*StdString(Namespace)*/)->emit("enable");//StdString(Name), StdString(Data));
    	UE_LOG(LogTemp, Log, TEXT("Emit %s with %s"), *Name, *Data);
    }
    i also tried "events" or "events/" to make sure its not a problem with the namespace. Here is a code snippet from the Unity Project the Server was originally created for (written in C#):
    Connect:
    Code:
    client = new Client("http://192.168.1.50:5000");
    
    		client.Error += SocketError;
    		client.Message += SocketMessage;
    
    		socket = client.Connect ("/events");
    Emit:
    Code:
    public void EventFanSpeed(int speed) {
    		if (oldSpeed == speed)
    			return;
    
    		socket.Emit("unityFanSpeedEvent", "" + speed, null);
    		oldSpeed = speed;
    	}
    Could it be that the Problem is that the server runs SocketIO 0.9?
    Last edited by Tyleet; 09-25-2016 at 07:07 AM.

  26. #26
    0
    Update to v0.2.0 for 4.13
    -Added connect/disconnect signatures (these have to be implemented by
    the server if used)
    -Added C++ lambda binds do e.g.
    BindDataLambdaToEvent([&](const FString& EventName, const FString& EventData) { //your code }, Name, Namespace);
    to use it
    -Bind changed name to BindEvent
    -Added Namespace support
    -Connection runs on background thread (should not be blocking anymore)

    Grab it at the github repo release
    https://github.com/getnamo/socketio-client-ue4/releases/tag/0.2.0


    Quote Originally Posted by Tyleet View Post
    ...

    Could it be that the Problem is that the server runs SocketIO 0.9?
    Try the newest release and let me know if it works. That said I believe the c++ client is using a 1.x version so there may be compatibility issues with a 0.x socket.io server.
    Last edited by getnamo; 10-01-2016 at 10:33 AM.

  27. #27
    0
    Hello getnamo, amazing plugin, I am just wondering is it possible to do all this socket.io bindings using code instead of BP?

  28. #28
    0
    Update to v0.2.1 for 4.13
    -added proper binary send/receive support
    -added functioning onconnect/disconnect events, no longer require
    special events on your server
    -added on namespace connect/disconnect events
    -added on fail event

    Grab it at the github repo releases url
    Code changes found in this merged commit


    Quote Originally Posted by Alexander Lean View Post
    Hello getnamo, amazing plugin, I am just wondering is it possible to do all this socket.io bindings using code instead of BP?
    Absolutely, I'm using this plugin in C++ for my own projects. Don't have a C++ how to atm, but here's a quick rundown:

    To use the C++ code from the plugin add it as a dependency module in your project build.cs

    Code:
    PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "SocketIOClient" });
    Add the component to your actor or reference it from another component by getting it on begin play e.g.

    Code:
    SIOComponent = Cast<USocketIOClientComponent>(this->GetOwner()->GetComponentByClass(USocketIOClientComponent::StaticClass()));
    if (!SIOComponent)
    {
    	UE_LOG(LogTemp, Warning, TEXT("No sister socket IO component found"));
    	return;
    }
    else
    {
    	UE_LOG(LogTemp, Log, TEXT("Found SIOComponent: %s"), *SIOComponent->GetDesc());
    }

    Connect:
    Code:
    //get a reference or add as subobject in your actor
    USocketIOClientComponent* SIOComponent;
    
    //the component will autoconnect, but you may wish to change the url before it does that via
    SIOComponent->AddressAndPort = FString("http://127.0.0.1:3000"); //change your address
    
    //you can also disable auto connect and connect it at your own time via
    SIOComponent->ShouldAutoConnect = false;
    SIOComponent->Connect(); // or SIOComponent->Connect("http://127.0.0.1:3000");

    String emit:
    Code:
    SIOComponent->Emit(FString(TEXT("myevent")), FString(TEXT("some data or stringified json"));
    note that namespaces are supported as a third optional FString parameter.

    Raw Data emit:
    Code:
    TArray<uint8> Buffer;
    
    //fill buffer with your data
    
    SIOComponent->EmitBuffer(FString(TEXT("myBinarySendEvent")), Buffer.GetData(), Buffer.Num());
    to receive events you can bind lambdas which makes things awesomely easy e.g.
    Code:
    SIOComponent->BindDataLambdaToEvent([&](const FString& Name, const FString& Data)
    		{
    			//do something with your string data
    		}, FString(TEXT("myStringReceiveEvent")));
    Raw data receive:
    Code:
    SIOComponent->BindBinaryMessageLambdaToEvent([&](const FString& Name, const TArray<uint8>& Buffer)
    		{
    			//Do something with your buffer
    		}, FString(TEXT("myBinaryReceiveEvent")));
    or if you want to deal with raw socket.io message data (this plugin doesn't have automatic UE json support yet)
    Code:
    SIOComponent->BindRawMessageLambdaToEvent([&](const FString& Name, const sio::message::ptr&)
    		{
    			//do something with your sio::message::ptr data 
    		}, FString(TEXT("myArbitraryReceiveEvent")));
    see https://github.com/socketio/socket.io-client-cpp/blob/master/src/sio_message.h for details on how to deal with raw sio messages.

    I'll hopefully consolidate the lambda types later on to handle UEJson format instead which will allow you to skip the stringification step on both sides if you want to build json objects. TBC!
    Last edited by getnamo; 10-02-2016 at 12:23 PM.

  29. #29
    0
    Wow amazing response! I 'm your fan now! Thanks a lot, I am just wondering about one thing, as I know socket.io is TCP based will it work on multiplayer games from 500-5000 players? Will it be as fast as UDP?

    Thanks!

  30. #30
    0
    Quote Originally Posted by Alexander Lean View Post
    Wow amazing response! I 'm your fan now! Thanks a lot, I am just wondering about one thing, as I know socket.io is TCP based will it work on multiplayer games from 500-5000 players? Will it be as fast as UDP?

    Thanks!
    Edit: forgot to mention TCP vs UDP

    Since Socket.io is based on websockets it can only use TCP. This can be a problem, see here this article: http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/ counterpoints: https://news.ycombinator.com/item?id=7289497

    In modern networks you don't get as many packet losses as you used to in the past. That said TCP performs worse than UDP for real-time loss tolerant applications because of its in-order setup. As a consequence you will receive old data, even if you have new data that can overwrite it which adds additional latency when you have packet losses. This means that your worst case scenarios will be worse than when using UDP. E.g. in a bad/unreliable connection your characters may appear frozen, and then unfreeze and do all their past movement really quickly vs just teleport to their latest position.

    In general I personally don't use socket.io for small real-time data e.g. character movement, for that I use UE4's network replication system.
    What I tend to use socket.io for is big data transfer (e.g. files) or logic events which aren't <1 second time sensitive (new file event, chat, data sharing events). But that doesn't mean it can't be used for that, WoW was notoriously based entirely on TCP!

    It's definitely easier to write logic in node.js than messing with UE4's dedicated server compilation and the mental gymnastics you have to do to understand the network replication system. It's a question of trade offs, when everything works with no packet losses, both of the solutions will look the same to the end user.


    In terms of overall throughput and performance, for that I point you to (~4 year old benchmark):
    http://drewww.github.io/socket.io-benchmarking/

    key takeaway:
    If I want to be able to support 5,000 concurrent users, a broadcast every second will use up basically half of my messaging capacity. If I have a chat room with 200 people in it sending a message a second on average, that's only about 2% of my capacity.
    Also

    My personal test of around ~ 300 chat windows spawned from the example project suggests its stable for chat traffic for that size and I've seen chats up to ~2k work well.

    That said, multiplayer traffic as a problem is an exponential function. To get high concurrency you need to cordon off sections of your traffic that don't interact to keep things smooth. Generally this means that if you can't see a user or they are far away, the server shouldn't emit that traffic to you. You can experiment with socket.io rooms/namespaces when you try scaling which will effectively cordon users off to their respective sub-area and you can always add more hardware scaling by having those rooms on different servers. In general though I don't think you would run into a problem until you're transmitting a lot of data or have hundreds of users even on a single server machine.

    So try to break it and then when you do finally hit the scaling problem, then optimize. Early optimizations usually just waste time as often your expectations != the actual situation.


    Unrelated to socket.io, but here's someone holding 1 Million long-poll connections active on a single node.js server (~16GB ram). It all depends on what you're doing, ram, connection speed, and overall expected throughput from each client.
    Last edited by getnamo; 11-06-2016 at 07:30 AM.

  31. #31
    0
    Update to 0.2.5
    -Change event names and signatures
    -Add wider support for raw message emitting and receiving

    Apart from adding the missing raw methods for C++ for callbacks and raw message types, I've added a little bit more about how to use the plugin in C++. I expect this to get a bit simpler as I get auto-json conversion working at some point. Grab the latest source at the repo https://github.com/getnamo/socketio-client-ue4

  32. #32
    0
    Update to 0.4.0
    -Added SIOJson for Blueprint Json construction and conversion, based on VaRest
    -Auto-conversion for nodes
    -Blueprint callbacks and events bound to functions references by function name
    -Conversion of JsonObjects to and from UStructs, including Blueprint UStructs with automatically trimmed long names into readable short names
    -Overloaded EmitNative for all expect UE native data types
    -Much simplified C++ usage based on FJsonValue and FJsonObject including nested binary support (hackery!)
    -and much more

    Grab it at the usual: https://github.com/getnamo/socketio-client-ue4/releases

    Seeing as I will probably use this plugin in production, decided to fix all major workflow issues with the plugin, it's accumulated so many changes for this update, it jumped two major versions internally! Check out the github readme for the latest examples and documentation!

    Some samples of the changes:

    Blueprint construction, thanks in large parts to SIOJson forked from ufna's VaRest


    Any unreal struct you make, including blueprint ones are supported for easy conversion to json!



    Binary and decode your complex nested data structures straight in blueprint


    Good workflow from auto-conversion for native types


    Callbacks, binding events to functions in your blueprints and encode/decode json straight from blueprints!




    Much improved C++ workflow based on native FJsonValue and FJsonObject. Support for nested raw binary data within these structures!

    Code:
    TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);                        //make object option2
    JsonObject->SetBoolField(FString("myBool"), false);
    JsonObject->SetStringField(FString("myString"), FString("Socket.io is easy"));
    JsonObject->SetNumberField(FString("myNumber"), 9001);
    
    JsonObject->SetField(FString("myBinary1"), USIOJConvert::ToJsonValue(Buffer));              //binary option1 - shorthand
    JsonObject->SetField(FString("myBinary2"), MakeShareable(new FJsonValueBinary(Buffer)));    //binary option2
    
    JsonObject->SetArrayField(FString("myArray"), ArrayValue);
    JsonObject->SetObjectField(FString("myNestedObject"), SmallObject);
    
    SIOClientComponent->EmitNative(FString("nativeTest"), JsonObject);
    Any UStruct to Json and easy c++ callbacks

    Code:
    //Set your struct variables
    FTestCppStruct TestStruct;
    TestStruct.Name = FString("George");
    TestStruct.Index = 5;
    TestStruct.SomeNumber = 5.123f;
    
    SIOClientComponent->EmitNative(FString("callbackTest"),  FTestCppStruct::StaticStruct(), &TestStruct, [&](auto Response)
    {
        auto Message = Response[0]->AsObject();
    
        //Show what we received
        UE_LOG(LogTemp, Log, TEXT("Received a response: %s"), *USIOJConvert::ToJsonString(Message));
    
        //Set our second struct to the new values
        USIOJConvert::JsonObjectToUStruct(Message, FTestCppStruct::StaticStruct(), &MemberStruct);
    
        //Show that struct
        UE_LOG(LogTemp, Log, TEXT("Our received member name is now: %s"), *MemberStruct.Name);
    });
    Last edited by getnamo; 11-17-2016 at 02:30 AM.

  33. #33
    0
    Quote Originally Posted by bot2600 View Post
    First, awesome work! And they are really clean to use from Blueprints. I do have one quick question though. I have a node server that I have been using as the backend for Unity and am looking to test it out against UE4, which there wasn't a client for socket.io when I first looked, so this is awesome!

    The issue I am running into is if I pass a JSON object instead of a string, I dont seem to get anything back from the plugin. Are there plans to support more advanced objects?

    Thanks!

    Edit: Adding screenshot, unless I call JSON.stringify on my objects this always goes to empty string

    Name:  json.png
Views: 3445
Size:  78.1 KB
    Just wanted to ping you, if you still want to use this plugin give the latest version a try, it can now handle all Json types straight in blueprints

  34. #34
    0
    Hi Getnamo,

    I saw you and we chatted at UE4London last week (i'm the gameshow guy) - thanks for another amazing demo! Afterwards we were talking about socket.io and all the cool stuff you've been doing with it so I thought i'd have a go at implementing it in my project (The gameshow).

    I'm quite interested in the auto-populating-struct from JSON functions, and i've had it working on a few tests. Is it possible to populate a struct containing an array of another type of struct? In my case i've got a QUESTION object (array of) which contains strings and some ints, but it also contains another array containing up to 4 ANSWER structs.

    I've tried to cobble this together (I'm populating it from outside, rather than converting the struct and sending it out of the engine) but I get an engine crash when I send in the data.

    Because of a weird issue I couldn't actually get my node server to communicate with the socket.io plugin you made - i'm just using the conversion nodes to convert stringified JSON to the struct - I don't know if that makes a difference.

    Dan.

  35. #35
    0
    Quote Originally Posted by Dannington View Post
    Hi Getnamo,

    I saw you and we chatted at UE4London last week (i'm the gameshow guy) - thanks for another amazing demo! Afterwards we were talking about socket.io and all the cool stuff you've been doing with it so I thought i'd have a go at implementing it in my project (The gameshow).

    I'm quite interested in the auto-populating-struct from JSON functions, and i've had it working on a few tests. Is it possible to populate a struct containing an array of another type of struct? In my case i've got a QUESTION object (array of) which contains strings and some ints, but it also contains another array containing up to 4 ANSWER structs.

    I've tried to cobble this together (I'm populating it from outside, rather than converting the struct and sending it out of the engine) but I get an engine crash when I send in the data.

    Because of a weird issue I couldn't actually get my node server to communicate with the socket.io plugin you made - i'm just using the conversion nodes to convert stringified JSON to the struct - I don't know if that makes a difference.

    Dan.
    Great to hear from you Dan!

    The key with JSON <-> struct conversion is that the keys have to match for the structure to fill properly.

    In both C++ and BP structs, UE4 follows PascalCase whereas JSON generally expects camelCase. UE4 json conversion automatically converts struct properties into camelCase, so this is the format your data should hold.

    E.g.:


    the vector struct will convert into
    Code:
    {
      "x": 1,
      "y": -22.3,
      "z": 9001.5
    }
    (note the lower case properties)

    So the first thing to check is to make sure all your json values use camelCase.

    Regarding struct of structs, in the tensorflow-ue4-mnist-example (final demo) I used a similar structure, I had a BP struct called DrawingStruct, which contained an array of StrokeStruct, these are then populated via json->struct conversion when the webclient sends strokes. So that method should work.

    Note that the json format for that example is something like:

    Code:
    {  
       "strokes":[  
          {  
             "stroke":[  
                {  
                   "x":3.9862472895741048,
                   "y":4.7506390606304745
                },
                {  
                   "x":4.0216255688082621,
                   "y":4.7864079379896598
                }
             ]
          },
          {  
             "stroke":[  
                {  
                   "x":20.610493174572404,
                   "y":4.2582182499755357
                },
                {  
                   "x":20.570929353931788,
                   "y":4.2949240704982428
                }
             ]
          }
       ]
    }
    This was essentially a workaround for an array of arrays in BPs.

    Regarding node.js communication, make sure you're using socket.io version 1.0.

    If those tips don't solve it, PM me your logs that you get from the crash and if you can post any BP graphs showing how it's linked up, maybe we can figure out what's the issue

  36. #36
    0
    Infiltrator
    Join Date
    Apr 2015
    Posts
    16
    Excited about your recent post @getnamo #tensorflowUE4, just saw it today - thanks !!
    https://github.com/getnamo/tensorflow-ue4-mnist-example


    Quote Originally Posted by getnamo View Post
    Great to hear from you Dan!

    The key with JSON <-> struct conversion is that the keys have to match for the structure to fill properly.

    In both C++ and BP structs, UE4 follows PascalCase whereas JSON generally expects camelCase. UE4 json conversion automatically converts struct properties into camelCase, so this is the format your data should hold.

    E.g.:


    the vector struct will convert into
    Code:
    {
      "x": 1,
      "y": -22.3,
      "z": 9001.5
    }
    (note the lower case properties)

    So the first thing to check is to make sure all your json values use camelCase.

    Regarding struct of structs, in the tensorflow-ue4-mnist-example (final demo) I used a similar structure, I had a BP struct called DrawingStruct, which contained an array of StrokeStruct, these are then populated via json->struct conversion when the webclient sends strokes. So that method should work.

    Note that the json format for that example is something like:

    Code:
    {  
       "strokes":[  
          {  
             "stroke":[  
                {  
                   "x":3.9862472895741048,
                   "y":4.7506390606304745
                },
                {  
                   "x":4.0216255688082621,
                   "y":4.7864079379896598
                }
             ]
          },
          {  
             "stroke":[  
                {  
                   "x":20.610493174572404,
                   "y":4.2582182499755357
                },
                {  
                   "x":20.570929353931788,
                   "y":4.2949240704982428
                }
             ]
          }
       ]
    }
    This was essentially a workaround for an array of arrays in BPs.

    Regarding node.js communication, make sure you're using socket.io version 1.0.

    If those tips don't solve it, PM me your logs that you get from the crash and if you can post any BP graphs showing how it's linked up, maybe we can figure out what's the issue

  37. #37
    0
    Quote Originally Posted by dr.purple View Post
    Excited about your recent post @getnamo #tensorflowUE4, just saw it today - thanks !!
    https://github.com/getnamo/tensorflow-ue4-mnist-example
    It needs a bit of work before it is drag and drop ready. Atm you need to install pip and tensorflow separately, but I'm making progress on encapsulating pip dependencies and python scripts into plugins themselves. That should in theory also allow other future python -> bp plugins to be built with drag and drop installation. Stay tuned
    Last edited by getnamo; 01-17-2017 at 06:33 PM.

  38. #38
    0
    Hi @getnamo - thanks for the tip on socket.io v1 - I expect it's that.

    I realised (I'm a java newbie) that on my node server and in the SQLite database I'm using, I was stringifying the answer's struct - so my json contained the normal strings and ints, but the answers were just an array of strings rather than valid json- it's been a whirlwind of learning this last 2 weeks!

    Cheers again though - I can see socket.io playing a huge part in my future projects. I might make a video tutorial like I did for Monsieur gustav's ue4osc plugin if I get a spare moment - what do you think? I was really interested when you first did your presentation on this but had absolutely no idea about how to set up a node server - I could do a really simple introduction to both, making a web interface into the engine.

  39. #39
    0
    Quote Originally Posted by Dannington View Post
    Hi @getnamo - thanks for the tip on socket.io v1 - I expect it's that.

    I realised (I'm a java newbie) that on my node server and in the SQLite database I'm using, I was stringifying the answer's struct - so my json contained the normal strings and ints, but the answers were just an array of strings rather than valid json- it's been a whirlwind of learning this last 2 weeks!

    Cheers again though - I can see socket.io playing a huge part in my future projects. I might make a video tutorial like I did for Monsieur gustav's ue4osc plugin if I get a spare moment - what do you think? I was really interested when you first did your presentation on this but had absolutely no idea about how to set up a node server - I could do a really simple introduction to both, making a web interface into the engine.
    Awesome to see good progress, learning something new is always challenging but worth it when it all clicks together. A video tutorial would be a great addition, looking forward to seeing what you come up with !

  40. #40
    0
    Hi @getnamo, nice work btw.

    My UE4Editor is crashing as soon as I am connecting to my server. I should say that I am not using an socket.io server. With javascript in a browser everything works fine (communication with a sps-controller). I am using version 4.14.3 of unreal.
    Do you have any ideas? I can't even debug because the whole Unreal crashes, only with a short info "not working any more..." It crashes both on blueprint and on c++. Tried also the latest release(0.4.1) and my own compilation with the latest source files from github (0.4.7).

    Thanks,
    Steffen

Page 1 of 3 123 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •