> RMC JAWS


“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;

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


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


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.