diff --git a/Source/Engine/Engine/Engine.Build.cs b/Source/Engine/Engine/Engine.Build.cs index e7bf85034..85c88024d 100644 --- a/Source/Engine/Engine/Engine.Build.cs +++ b/Source/Engine/Engine/Engine.Build.cs @@ -37,6 +37,7 @@ public class Engine : EngineModule options.PublicDependencies.Add("Utilities"); options.PublicDependencies.Add("Visject"); options.PublicDependencies.Add("Localization"); + options.PublicDependencies.Add("Online"); // Use source folder per platform group switch (options.Platform.Target) diff --git a/Source/Engine/Online/IOnlinePlatform.h b/Source/Engine/Online/IOnlinePlatform.h new file mode 100644 index 000000000..6d387021d --- /dev/null +++ b/Source/Engine/Online/IOnlinePlatform.h @@ -0,0 +1,237 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +#pragma once + +#include "Online.h" +#include "Engine/Core/Types/Span.h" +#include "Engine/Core/Types/String.h" +#include "Engine/Core/Types/DateTime.h" + +/// +/// Online platform user presence common states. +/// +API_ENUM(Namespace="FlaxEngine.Online") enum class OnlinePresenceStates +{ + /// + /// User is offline. + /// + Offline = 0, + + /// + /// User is online. + /// + Online, + + /// + /// User is online but busy. + /// + Busy, + + /// + /// User is online but away (no activity for some time). + /// + Away, +}; + +/// +/// Online platform user description. +/// +API_STRUCT(Namespace="FlaxEngine.Online") struct FLAXENGINE_API OnlineUser +{ + DECLARE_SCRIPTING_TYPE_MINIMAL(OnlineUser); + + /// + /// Unique player identifier. Specific for a certain online platform. + /// + API_FIELD() Guid Id; + + /// + /// The player name. + /// + API_FIELD() String Name; + + /// + /// The current player presence state. + /// + API_FIELD() OnlinePresenceStates PresenceState; +}; + +/// +/// Online platform achievement description. +/// +API_STRUCT(Namespace="FlaxEngine.Online") struct FLAXENGINE_API OnlineAchievement +{ + DECLARE_SCRIPTING_TYPE_MINIMAL(OnlineAchievement); + + /// + /// Unique achievement identifier. Specific for a certain online platform. + /// + API_FIELD() String Identifier; + + /// + /// Achievement name. Specific for a game. + /// + API_FIELD() String Name; + + /// + /// The achievement title text. + /// + API_FIELD() String Title; + + /// + /// The achievement description text. + /// + API_FIELD() String Description; + + /// + /// True if achievement is hidden from user (eg. can see it once it's unlocked). + /// + API_FIELD() bool IsHidden = false; + + /// + /// Achievement unlock percentage progress (normalized to 0-100 range). + /// + API_FIELD() float Progress = 0.0f; + + /// + /// Date and time at which player unlocked the achievement. + /// + API_FIELD() DateTime UnlockTime = DateTime::MinValue(); +}; + +/// +/// Interface for online platform providers for communicating with various multiplayer services such as player info, achievements, game lobby or in-game store. +/// +API_INTERFACE(Namespace="FlaxEngine.Online") class FLAXENGINE_API IOnlinePlatform +{ + DECLARE_SCRIPTING_TYPE_MINIMAL(IOnlinePlatform); + + /// + /// Finalizes an instance of the class. + /// + virtual ~IOnlinePlatform() = default; + + /// + /// Initializes the online platform services. + /// + /// Called only by Online system. + /// True if failed, otherwise false. + API_FUNCTION() virtual bool Initialize() = 0; + + /// + /// Shutdowns the online platform services. + /// + /// Called only by Online system. Can be used to destroy the object. + API_FUNCTION() virtual void Deinitialize() = 0; + +public: + /// + /// Logins the local user into the online platform. + /// + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool UserLogin(User* localUser = nullptr) = 0; + + /// + /// Logout the local user from the online platform. + /// + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool UserLogout(User* localUser = nullptr) = 0; + + /// + /// Checks if the local user is logged in. + /// + /// The local user (null if use default one). + /// True if user is logged, otherwise false. + API_FUNCTION() virtual bool GetUserLoggedIn(User* localUser = nullptr) = 0; + + /// + /// Gets the player from the online platform. + /// + /// The local player user info. + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool GetUser(API_PARAM(Out) OnlineUser& user, User* localUser = nullptr) = 0; + + /// + /// Gets the list of friends of the user from the online platform. + /// + /// The result local player friends user infos. + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool GetFriends(API_PARAM(Out) Array& friends, User* localUser = nullptr) = 0; + +public: + /// + /// Gets the list of all achievements for this game. + /// + /// The result achievements list + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool GetAchievements(API_PARAM(Out) Array& achievements, User* localUser = nullptr) = 0; + + /// + /// Unlocks the achievement. + /// + /// The achievement name. Specific for a game. + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool UnlockAchievement(const StringView& name, User* localUser = nullptr) = 0; + + /// + /// Updates the achievement unlocking progress (in range 0-100). + /// + /// The achievement name. Specific for a game. + /// The achievement unlock progress (in range 0-100). + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool UnlockAchievementProgress(const StringView& name, float progress, User* localUser = nullptr) = 0; + +#if !BUILD_RELEASE + /// + /// Resets the all achievements progress for this game. + /// + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool ResetAchievements(User* localUser = nullptr) = 0; +#endif + +public: + /// + /// Gets the online statistical value. + /// + /// The stat name. + /// The result value. + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool GetStat(const StringView& name, API_PARAM(Out) float& value, User* localUser = nullptr) = 0; + + /// + /// Sets the online statistical value. + /// + /// The stat name. + /// The value. + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool SetStat(const StringView& name, float value, User* localUser = nullptr) = 0; + +public: + /// + /// Gets the online savegame data. Returns empty if savegame slot is unused. + /// + /// The savegame slot name. + /// The result data. Empty or null for unused slot name. + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool GetSaveGame(const StringView& name, API_PARAM(Out) Array& data, User* localUser = nullptr) = 0; + + /// + /// Sets the online savegame data. + /// + /// The savegame slot name. + /// The data. Empty or null to delete slot (or mark as unused). + /// The local user (null if use default one). + /// True if failed, otherwise false. + API_FUNCTION() virtual bool SetSaveGame(const StringView& name, const Span& data, User* localUser = nullptr) = 0; +}; diff --git a/Source/Engine/Online/Online.Build.cs b/Source/Engine/Online/Online.Build.cs new file mode 100644 index 000000000..bb4ff1ba5 --- /dev/null +++ b/Source/Engine/Online/Online.Build.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +using Flax.Build; + +/// +/// Online services base module. +/// +public class Online : EngineModule +{ +} diff --git a/Source/Engine/Online/Online.cpp b/Source/Engine/Online/Online.cpp new file mode 100644 index 000000000..ca53ed78e --- /dev/null +++ b/Source/Engine/Online/Online.cpp @@ -0,0 +1,51 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +#include "Online.h" +#include "IOnlinePlatform.h" +#include "Engine/Core/Log.h" +#include "Engine/Engine/EngineService.h" +#include "Engine/Scripting/ScriptingObject.h" + +class OnlineService : public EngineService +{ +public: + OnlineService() + : EngineService(TEXT("Online"), 100) + { + } + + void Dispose() override + { + // Cleanup current online platform + Online::Initialize(nullptr); + } +}; + +IOnlinePlatform* Online::Platform = nullptr; +Action Online::PlatformChanged; +OnlineService OnlineServiceInstance; + +bool Online::Initialize(IOnlinePlatform* platform) +{ + if (Platform == platform) + return false; + const auto object = ScriptingObject::FromInterface(platform, IOnlinePlatform::TypeInitializer); + LOG(Info, "Changing online platform to {0}", object ? object->ToString() : (platform ? TEXT("?") : TEXT("none"))); + + if (Platform) + { + Platform->Deinitialize(); + } + Platform = platform; + if (Platform) + { + if (Platform->Initialize()) + { + Platform = nullptr; + LOG(Error, "Failed to initialize online platform."); + return true; + } + } + + return false; +} diff --git a/Source/Engine/Online/Online.h b/Source/Engine/Online/Online.h new file mode 100644 index 000000000..7d8bdc820 --- /dev/null +++ b/Source/Engine/Online/Online.h @@ -0,0 +1,35 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +#pragma once + +#include "Engine/Core/Delegate.h" +#include "Engine/Scripting/ScriptingType.h" + +class IOnlinePlatform; + +/// +/// The online system for communicating with various multiplayer services such as player info, achievements, game lobby or in-game store. +/// +API_CLASS(Static, Namespace="FlaxEngine.Online") class FLAXENGINE_API Online +{ + DECLARE_SCRIPTING_TYPE_NO_SPAWN(Online); +public: + /// + /// The current online platform. + /// + API_FIELD(ReadOnly) static IOnlinePlatform* Platform; + + /// + /// Event called when current online platform gets changed. + /// + API_EVENT() static Action PlatformChanged; + +public: + /// + /// Initializes the online system with a given online platform implementation. + /// + /// Destroys the current platform (in any already in-use). + /// The online platform object. + /// True if failed, otherwise false. + API_FUNCTION() static bool Initialize(IOnlinePlatform* platform); +};