Skip to content

Commit

Permalink
Integrate match-making server in UnrealLibretro
Browse files Browse the repository at this point in the history
  • Loading branch information
N7Alpha committed Jun 9, 2024
1 parent 9ce3f74 commit c8ae549
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 7 deletions.
1 change: 1 addition & 0 deletions Source/UnrealLibretro/Private/LibretroContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extern void LibretroSam2LogWrite(int level, const char* file, int line, const ch

#define ULNET_IMPLEMENTATION
#define ULNET_IMGUI
#define SAM2_SERVER
#define SAM2_IMPLEMENTATION

#define SAM2_LOG_WRITE(level, file, line, ...) LibretroSam2LogWrite(level, file, line, "Netplay: " __VA_ARGS__)
Expand Down
135 changes: 135 additions & 0 deletions Source/UnrealLibretro/Private/LibretroThirdPartyImplementation.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#pragma warning(disable: 4456) // declaration of 'variable' hides previous local declaration
#pragma warning(disable: 4510) // default constructor could not be generated
#pragma warning(disable: 4610) // object can never be instantiated - user-defined constructor required
#pragma warning(disable: 4668)
#pragma warning(disable: 4800) // Implicit conversion from 'type' to bool. Possible information loss
#pragma warning(disable: 4946) // reinterpret_cast used between related classes
#pragma warning(disable: 4996) // 'item' was declared deprecated
Expand Down Expand Up @@ -51,11 +52,15 @@
// - We don't have to worry about loading the dll
// - We aren't at risk of polluting the symbol-space
// This may end up being unmaintainable in which case I'll do something more sane
// MARK: libjuice
#pragma push
#define __STDC_VERSION__ 0
#define RELEASE 0
#define JUICE_ENABLE_LOCALHOST_ADDRESS 0
#define JUICE_STATIC
#ifdef _WIN32
#pragma comment(lib, "bcrypt.lib")
#endif
//#include "Windows/AllowWindowsPlatformTypes.h"
#include "../../ThirdParty/libjuice/src/addr.c"
#include "../../ThirdParty/libjuice/src/agent.c"
Expand Down Expand Up @@ -83,6 +88,7 @@
#include "../../ThirdParty/libjuice/src/turn.c"
#include "../../ThirdParty/libjuice/src/udp.c"

// MARK: zstd
#define ZSTD_LEGACY_SUPPORT 0
#define ZSTDLIB_STATIC_API
#define ZDICTLIB_STATIC_API
Expand Down Expand Up @@ -122,3 +128,132 @@
#include "../../ThirdParty/zstd/lib/dictBuilder/fastcover.c"
#include "../../ThirdParty/zstd/lib/dictBuilder/zdict.c"
#endif

// MARK: libuv
// Non platform-specific files
#include "../../ThirdParty/libuv/src/fs-poll.c"
#include "../../ThirdParty/libuv/src/idna.c"
#include "../../ThirdParty/libuv/src/inet.c"
#include "../../ThirdParty/libuv/src/random.c"
#include "../../ThirdParty/libuv/src/strscpy.c"
#include "../../ThirdParty/libuv/src/strtok.c"
#include "../../ThirdParty/libuv/src/thread-common.c"
#include "../../ThirdParty/libuv/src/timer.c"
#include "../../ThirdParty/libuv/src/uv-common.c"
#include "../../ThirdParty/libuv/src/uv-data-getter-setters.c"
#include "../../ThirdParty/libuv/src/version.c"

// Windows-specific files
#ifdef _WIN32
#pragma comment(lib, "Userenv.lib")
#include "../../ThirdParty/libuv/src/win/async.c"
#include "../../ThirdParty/libuv/src/win/core.c"
#include "../../ThirdParty/libuv/src/win/detect-wakeup.c"
#include "../../ThirdParty/libuv/src/win/dl.c"
#include "../../ThirdParty/libuv/src/win/error.c"
#include "../../ThirdParty/libuv/src/win/fs.c"
#include "../../ThirdParty/libuv/src/win/fs-event.c"
#include "../../ThirdParty/libuv/src/win/getaddrinfo.c"
#include "../../ThirdParty/libuv/src/win/getnameinfo.c"
#include "../../ThirdParty/libuv/src/win/handle.c"
#include "../../ThirdParty/libuv/src/win/loop-watcher.c"
#include "../../ThirdParty/libuv/src/win/pipe.c"
#include "../../ThirdParty/libuv/src/win/poll.c"
#include "../../ThirdParty/libuv/src/win/process.c"
#include "../../ThirdParty/libuv/src/win/process-stdio.c"
#include "../../ThirdParty/libuv/src/win/signal.c"
#include "../../ThirdParty/libuv/src/win/snprintf.c"
#include "../../ThirdParty/libuv/src/win/stream.c"
#define uv_zero_ uv_zero_2
#include "../../ThirdParty/libuv/src/win/tcp.c"
#include "../../ThirdParty/libuv/src/win/thread.c"
#define uv_null_buf_ uv_null_buf_2
#include "../../ThirdParty/libuv/src/win/tty.c"
#define uv_zero_ uv_zero_3
#include "../../ThirdParty/libuv/src/win/udp.c"
#include "../../ThirdParty/libuv/src/win/util.c"
#include "../../ThirdParty/libuv/src/win/winapi.c"
#include "../../ThirdParty/libuv/src/win/winsock.c"
#endif

// Unix-specific files common to Linux, macOS, and BSD
#if defined(__unix__) || defined(__APPLE__)
#include "../../ThirdParty/libuv/src/unix/async.c"
#include "../../ThirdParty/libuv/src/unix/core.c"
#include "../../ThirdParty/libuv/src/unix/dl.c"
#include "../../ThirdParty/libuv/src/unix/fs.c"
#include "../../ThirdParty/libuv/src/unix/getaddrinfo.c"
#include "../../ThirdParty/libuv/src/unix/getnameinfo.c"
#include "../../ThirdParty/libuv/src/unix/loop-watcher.c"
#include "../../ThirdParty/libuv/src/unix/loop.c"
#include "../../ThirdParty/libuv/src/unix/pipe.c"
#include "../../ThirdParty/libuv/src/unix/poll.c"
#include "../../ThirdParty/libuv/src/unix/process.c"
#include "../../ThirdParty/libuv/src/unix/signal.c"
#include "../../ThirdParty/libuv/src/unix/stream.c"
#include "../../ThirdParty/libuv/src/unix/tcp.c"
#include "../../ThirdParty/libuv/src/unix/thread.c"
#include "../../ThirdParty/libuv/src/unix/tty.c"
#include "../../ThirdParty/libuv/src/unix/udp.c"
#endif

// Additional files specific to macOS (Darwin)
#ifdef __APPLE__
#include "../../ThirdParty/libuv/src/unix/darwin.c"
#include "../../ThirdParty/libuv/src/unix/darwin-proctitle.c"
#include "../../ThirdParty/libuv/src/unix/fsevents.c"
#endif

// Additional files specific to Linux (Including Android)
#ifdef __linux__
#include "../../ThirdParty/libuv/src/unix/linux.c"
#include "../../ThirdParty/libuv/src/unix/procfs-exepath.c"
#include "../../ThirdParty/libuv/src/unix/random-getrandom.c"
#include "../../ThirdParty/libuv/src/unix/random-sysctl-linux.c"
#endif

// Additional files specific to Android
#if defined(__ANDROID__)
#include "../../ThirdParty/libuv/src/unix/random-getentropy.c"
#include "../../ThirdParty/libuv/src/unix/proctitle.c"
#endif

// Additional files specific to FreeBSD
#ifdef __FreeBSD__
#include "../../ThirdParty/libuv/src/unix/freebsd.c"
#endif

// Additional files specific to OpenBSD
#ifdef __OpenBSD__
#include "../../ThirdParty/libuv/src/unix/openbsd.c"
#endif

// Additional files specific to NetBSD
#ifdef __NetBSD__
#include "../../ThirdParty/libuv/src/unix/netbsd.c"
#endif

// Additional files specific to BSDs
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#include "../../ThirdParty/libuv/src/unix/bsd-ifaddrs.c"
#include "../../ThirdParty/libuv/src/unix/kqueue.c"
#endif

// Generic Unix files not specific to any above category
#if defined(__unix__) || defined(__APPLE__)
#include "../../ThirdParty/libuv/src/unix/posix-hrtime.c"
#include "../../ThirdParty/libuv/src/unix/posix-poll.c"
#endif

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4459)
#endif

// This source file defines static variables with names like mutex and cond which are very
// likely to conflict with local definitions so I stuck it at the bottom here
#include "../../ThirdParty/libuv/src/threadpool.c"

#ifdef _MSC_VER
#pragma warning(pop)
#endif
52 changes: 52 additions & 0 deletions Source/UnrealLibretro/Private/UnrealLibretro.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#include "UnrealLibretro.h"

#define SAM2_SERVER
THIRD_PARTY_INCLUDES_START
#include "sam2.h"
THIRD_PARTY_INCLUDES_END

#include "Misc/MessageDialog.h"
#include "Modules/ModuleManager.h"

Expand All @@ -19,6 +24,40 @@ PFN_wglGetProcAddress _wglGetProcAddress;

char UnrealLibretroVersionAnsi[256] = {0}; // IModuleInterface can give you this but it's GameThread only

class FSam2ServerRunnable : public FRunnable
{
public:
FSam2ServerRunnable()
{
int server_size_bytes = sam2_server_create(NULL, 0);

Sam2Server = (sam2_server_t*)malloc(server_size_bytes);
sam2_server_create(Sam2Server, SAM2_SERVER_DEFAULT_PORT);
}

~FSam2ServerRunnable()
{
free(Sam2Server);
}

virtual uint32 Run() override
{
// Handle TCP requests. This call returns only after calling uv_stop()
uv_run(&Sam2Server->loop, UV_RUN_DEFAULT);

// Start asynchronous destruction
sam2_server_begin_destroy(Sam2Server);

// Do the needful
uv_run(&Sam2Server->loop, UV_RUN_DEFAULT);
uv_loop_close(&Sam2Server->loop);

return 0;
}

sam2_server_t* Sam2Server;
};

void FUnrealLibretroModule::StartupModule()
{
check(IsInGameThread()); // For IPluginManager
Expand All @@ -29,6 +68,9 @@ void FUnrealLibretroModule::StartupModule()

FCStringAnsi::Strncpy(UnrealLibretroVersionAnsi, TCHAR_TO_ANSI(*VersionName), sizeof(UnrealLibretroVersionAnsi) - 1);

Sam2ServerRunnable = new FSam2ServerRunnable();
Sam2ServerThread = FRunnableThread::Create(Sam2ServerRunnable, TEXT("Sam2ServerThread"));

// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
#define LIBRETRO_NOTE " Note: disable UnrealLibretro or delete the UnrealLibretro plugin to make this error go away." \
" You can also post an issue to github."
Expand Down Expand Up @@ -61,6 +103,16 @@ void FUnrealLibretroModule::StartupModule()

void FUnrealLibretroModule::ShutdownModule()
{
if (Sam2ServerThread)
{
uv_stop(&Sam2ServerRunnable->Sam2Server->loop);
Sam2ServerThread->WaitForCompletion();
delete Sam2ServerThread;
delete Sam2ServerRunnable;
Sam2ServerRunnable = nullptr;
Sam2ServerThread = nullptr;
}

// @todo For now I skip resource cleanup. It could be added back if I added isReadyForFinishDestroy(bool) to ULibretroCoreInstance
// in conjunction with waiting for the FLibretroContext to destruct since UE uses the outstanding UObjects from this module visible through
// the reflection system (UProperty, etc) to determine when it is safe to shutdown this module.
Expand Down
2 changes: 2 additions & 0 deletions Source/UnrealLibretro/Public/UnrealLibretro.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ class FUnrealLibretroModule : public IModuleInterface
}

private:
class FSam2ServerRunnable* Sam2ServerRunnable = nullptr;
FRunnableThread* Sam2ServerThread = nullptr;

#ifdef PLATFORM_WINDOWS
FString RedistDirectory;
Expand Down
13 changes: 6 additions & 7 deletions Source/UnrealLibretro/UnrealLibretro.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ public UnrealLibretro(ReadOnlyTargetRules Target) : base(Target)
{
PrivateDependencyModuleNames.Add("AudioExtensions");
}

PrivateDependencyModuleNames.AddRange(new string[] { "Sockets", "Networking" }); // NetImgui

// NetImgui
PrivateDependencyModuleNames.AddRange(new string[] { "Sockets", "Networking" });
//PrivateIncludePaths.Add(PluginDirectory + "/Source/UnrealLibretro/netImgui");
//PCHUsage = PCHUsageMode.NoSharedPCHs; // Prevents problem with Dear ImGui/NetImgui sources not including the right first header
//PrivatePCHHeaderFile = "Public/UnrealLibretro.h";
Expand All @@ -83,11 +84,9 @@ public UnrealLibretro(ReadOnlyTargetRules Target) : base(Target)
PrivateIncludePaths.Add("$(PluginDir)/../ThirdParty/libjuice/include");
PrivateIncludePaths.Add("$(PluginDir)/../ThirdParty/libjuice/include/juice"); // We #include libjuice implementation files which expect this

if (Target.Platform == UnrealTargetPlatform.Win64)
{
// Link against the bcrypt library
PublicAdditionalLibraries.Add("bcrypt.lib");
}
// libuv stuff
PrivateIncludePaths.Add("$(PluginDir)/../ThirdParty/libuv/include");
PrivateIncludePaths.Add("$(PluginDir)/../ThirdParty/libuv/src");

// imgui stuff
PrivateDefinitions.Add("IMGUI_DEFINE_MATH_OPERATORS"); // We get unity build issues/packaging issues if this isn't defined
Expand Down

0 comments on commit c8ae549

Please sign in to comment.