“The network is the computer.”
– J. Gage
With this key area of my portfolio, I bring Best Practices and Optimization techniques.
Below I discuss a client-server API for gaming. If you want to see other backend topics, see these;
- For real-time, shared experiences, checkout my dedicated Multiplayer Portfolio
- For the main page on backend, see my Backend Portfolio
Interested to collaborate on JAWS?
RMC
Together with my teams, I have released free and premium code packages released under Rivello Multimedia Consulting (RMC) including Unity and Godot tooling and APIs. Checkout the highlights.
RMC JAWS
While finishing an Amazon Web Server (AWS) Gaming integration, I refined the API and generalized it for educational and development use-cases.
RMC JAWS demonstrates my philosophy to API design, my development approach, and competence in using backend services.
- Just
- Amazon
- Web
- Services
Subsystems
- Jaws.Instance.Accounts – Responsible for user authentication
- Jaws.Instance.Database – Manages server data
- Jaws.Instance.CloudCode – Calls server functionality
Philosophy
- Easy to learn
- Easy to use
- Hard to misuse
Possible Expedient Solutions
- Hacks: During development, some ‘cheats’ may be employed like a hardcoded backend account, a simplified database table, etc…
Scope: Goals
- User Accounts
- Database (CRUD)
- Cloud Code
Scope: Goals (Stretch)
- Abstract the C# base types used for JAWS to allow for a separate, sibling API powered by a competitor (e.g. Google Firebase) instead
JAWS API
This RMC Backend library has a main BackendSystem
(e.g. JAWS.Instance
) with subsystems of Accounts
, Database
, and CloudCode
. The architecture is flexible too. Developers can scale it by adding and updating new subsystems for specific needs.
This is a custom API created by RMC.
1. Accounts 👨💼
Accounts
is responsible for user authentication.
// // Observe Jaws.Instance.OnInitialized.AddListener((jaws) => { Debug.LogWarning("@@ Jaws.OnInitialized()"); }); Jaws.Instance.Accounts.OnUserCreate.AddListener((accounts) => { Debug.LogWarning("@@ Jaws.OnUserCreate()"); }); Jaws.Instance.Accounts.OnUserDelete.AddListener((accounts) => { Debug.LogWarning("@@ Jaws.OnUserDelete()"); }); Jaws.Instance.Accounts.OnUserSignIn.AddListener((accounts) => { Debug.LogWarning("@@ Jaws.OnUserSignIn()"); }); Jaws.Instance.Accounts.OnUserSignOut.AddListener((accounts) => { Debug.LogWarning("@@ Jaws.OnUserSignOut()"); }); // Initialize await Jaws.Instance.InitializeAsync(); // Prepare string userEmail = "test@email.com"; string userPassword = "abc123"; string userNickname = "testName"; // Check if (!Jaws.Instance.Accounts.HasUser()) { // Create User var createUserResponse = await Jaws.Instance.Accounts.UserCreateAsync(userEmail, userPassword, userNickname); if (!createUserResponse.IsSuccess) { Debug.Log($"{createUserResponse.ErrorMessage}"); return; } // SignIn User var signInUserResponse = await Jaws.Instance.Accounts.UserSignInAsync(userEmail, userPassword); if (!signInUserResponse.IsSuccess) { Debug.Log($"{createUserResponse.ErrorMessage}"); return; } // Response Debug.Log($"Result = {signInUserResponse.User.Email}"); } //
2. Database 💾
Database
is responsible for managing server data.
// // Observe Jaws.Instance.OnInitialized.AddListener((jaws) => { Debug.LogWarning("@@ Jaws.OnInitialized()"); }); Jaws.Instance.Database.OnTableRead.AddListener((database) => { Debug.LogWarning("@@ Jaws.OnTableRead()"); }); Jaws.Instance.Database.OnItemCreate.AddListener((database) => { Debug.LogWarning("@@ Jaws.OnItemCreate()"); }); Jaws.Instance.Database.OnItemRead.AddListener((database) => { Debug.LogWarning("@@ Jaws.OnItemRead()"); }); Jaws.Instance.Database.OnItemUpdate.AddListener((database) => { Debug.LogWarning("@@ Jaws.OnItemUpdate()"); }); // Initialize await Jaws.Instance.InitializeAsync(); // Prepare var user = Jaws.Instance.Accounts.GetUser(); var table = new Table("InventoryTable"); var item = new Item("Gold"); // Check if (user != null) { // Add Item To Table var itemCreateResponse = await Jaws.Instance.Database.ItemCreateAsync(table, user, item); if (!itemCreateResponse.IsSuccess) { Debug.Log($"{itemCreateResponse .ErrorMessage}"); return; } // Response Debug.Log($"Result = {itemCreateResponse.Item.Quantity} of {itemCreateResponse.Item.Name}"); } //
3. CloudCode ☁️
CloudCode
is responsible for calling server-side code.
// // Observe Jaws.Instance.OnInitialized.AddListener((jaws) => { Debug.LogWarning("@@ Jaws.OnInitialized()"); }); Jaws.Instance.CloudCode.OnMethodCall.AddListener((cloudCode) => { Debug.LogWarning("@@ Jaws.OnMethodCall()"); }); // Initialize await Jaws.Instance.InitializeAsync(); // Prepare string functionName = "HelloWorld"; Dictionary<string, string> args = new Dictionary<string, string>(); args.Add("message", "this is from the client"); // Check if (user != null) { // Call Server Code var methodCallResponse = await Jaws.Instance.CloudCode.MethodCallAsync<string>(functionName, args); if (!methodCallResponse.IsSuccess) { Debug.Log($"{methodCallResponse.ErrorMessage}"); return; } // Response Debug.Log($"Result = {response.Data}"); } //
Downloads
This repo is the ideal starting point for new Unity projects with AWS using RMC Jaws.
Repos
- GitHub.com/SamuelAsherRivello/rmc-jaws – This package contains the library and samples. Great to pull into your own project!
- GitHub.com/SamuelAsherRivello/rmc-jaws-demo – This project contains the library and samples. Great to try out the functionality in an existing project!
What’s Next?
This area of my expertise is particularly exciting!I love to learn & to make an impact with my teams and projects.
Contact me regarding new opportunities that align with my skills and experience.