• Building
    • Firedancer
    • the Pit
    • Cyclone
  • Thinking
  • Connect
  • Building
    • Firedancer
    • the Pit
    • Cyclone
    • Collaborations
  • Thinking
  • About
Terms of Use_Privacy Policy_Disclaimers_

Gaming Infrastructure Part 2: Introduction to ARC

Dev Bharel
Dev Bharel
Shanav K Mehta
Shanav K Mehta
GamingInfrastructureResearch

Jan 09 2023 _ 7 min read

Gaming Infrastructure Part 2: Introduction to ARC

Overview

In the last post, we discussed three types of on-chain games, namely (i) fully on-chain games (FOC), (ii) on-chain assets (OCA), and (iii) optional cosmetic mints (OCM). To recap, most game studios today opt for the OCM approach due to limited available infrastructure to pursue FOC and OCA without introducing substantial user friction. Over the next few articles, we will highlight some of the infrastructure that could enable fully on-chain games (FOC) and on-chain assets (OCA), along with rough designs of what each component might look like in production.

The first piece of infrastructure needed is an efficient system to manage assets as well as game state on-chain. Defining how the asset operates on-chain has meaningful downstream implications on asset programmability (e.g. permissioning, metadata updates etc). To better understand what such a system could look like, we decided to build our own on-chain game (more on this later) and rapidly found that traditional object-oriented programming (OOP)-based approaches run into scalability challenges as asset dependencies increase linearly as the scope of the game expands.

As a result, we decided to experiment with data-oriented design patterns that have been long used by traditional game developers but have scarcely been experimented with on-chain. Through this process, we experimented with a framework we call ARC (Action Registry Core) on Solana that we believe is one of the most efficient ways to manage on-chain assets and game logic. ARC is inspired by a data-oriented architectural pattern called ECS (Entity Component System) that is often used in traditional game development.

In this article, we will go over how ECS works, why it is important in traditional games, how this philosophy could be extended to build a framework like ARC, and what the underlying architecture would look like.

Our goal from this exercise is to contribute to open research and help push on-chain gaming infrastructure forward. In that spirit, we have decided to open source our reference implementation of ARC and welcome any feedback from the community.

Link to ARC GitHub

What Is ECS in Traditional Game Development?

ECS, or (”Entity Component System”), is an architecture that’s been widely adopted in recent years for video games. Compared to classic Object-Oriented Programming (OOP), ECS has a number of benefits for video games as it separates data from behavior. In traditional web2 games, this has great performance boosts (improved cache locality) while also maintaining better logic controls while developing the game itself.

A helpful way to understand the benefits of ECS is to understand the shortcomings of traditional OOP in scenarios with multiple dependencies.

Challenges with OOP - The Diamond Problem

Let’s say we’re building a very simple game which has the following properties:

  • Three entities: i) Mammal, ii) Fish, iii) Amphibian
  • Mammal can breathe on land but not in water
  • Fish can breathe in water but not on land
  • Amphibian can breathe both in water and on land

In traditional OOP, Mammal could be an entity than inherits from a base class LandBreather and Fishcould be an entity than inherits from a base class WaterBreather. We run into a challenge with Amphibian here where it has the properties of both LandBreather and WaterBreather but cannot inherit from both. In classic OOP, this is called the “Diamond Problem.” This problem is more prevalent in games than other applications as the number of game characters, items, and asset compounds with increasing characteristics and dependencies. While some workarounds exist, for gaming, we believe ECS is the most elegant solution

ECS as a Solution

An ECS-based game has the following properties:

  • Entities - unique identifiers or containers for components
  • Components - plain data types without behavior, that can be “attached” to entities
  • Systems - functions matched with entities that have a certain set of components

Entities can contain zero or more components. Entities can add/remove/modify their components dynamically through the use of Systems.

To understand how ECS solves the constraints faced by OOP within games, let’s use ECS to solve for the example above. Under ECS we would create two components: LandBreather and WaterBreather. The system LandBreatherSystem handles movement of any entity with the LandBreather component and WaterBreatherSystem handles movement of any entity with the WaterBreather component. Entities could then look as follows:

  • Mammal: [LandBreather]
  • Fish: [WaterBreather]
  • Amphibian:  [LandBreather, WaterBreather]

You can then dynamically add more components to entities such as Fly or Fight and create more entities with varying components under them.

What Is ARC?

ARC (Action Registry Core) is a framework for organizing information on-chain that is inspired by traditional ECS architecture. Like traditional ECS, ARC has entities that are data-less containers for components and components that are plain data types without behavior that can be “attached” to entities.

Unlike ECS, ARC has ‘actions’ instead of ‘systems’ that can execute against specific components. The primary distinction is that systems in traditional ECS are built around a loop-based architecture used in traditional games, whereas action bundles account for the fact that blockchain architecture is push-based. The specific implementation of ARC outlined here is for the Solana ecosystem, but a similar architecture could be used in other ecosystems as well. The basic structure for ARC is a three-layered onion. First, you have the Core, which is in charge of maintaining the Registries and Entities. Secondly, you have various Registry contracts, that maintain registrations for Components and Actions, along with governance features. And finally, you have the (optional) games or Actions contracts that modify components.

The Core:

The Core is in charge of exactly three things:

  • Initiation of new Registry instances
  • Minting of new entities either as NFTs or standalone entity PDAs
  • Maintenance of SerializedComponents with respect to an entity

Only one Core program ever needs to exist on the chain, as Registry Instances are how we bucket different components, entities, and rules. On EVM chains this approach might not work, as contract storage is limited per contract, meaning it might be better to launch multiple Cores.

Specifically in Solana, the Entity structure is similar to Metaplex Metadata generated for each Metaplex NFT. One significant difference is the new mapping of one Entity per Registry instance on a given token. This means that one token could theoretically hold multiple entities, as long as they belong to different Registries (will likely have different components, component values, etc).

It’s an open question if this behavior is “better” than one entity per token. Because the Core only deals with serialized components, it doesn’t need to worry about how to deserialize anything. This means all deserialization logic can be pushed to the game, or Actions level.

A Registry instance is a unique identifier given to a Registry and its instance ID. Different instances help instantiate different “games” in the same Core, allowing for reuse of the same Registry Governance code for a given set of components and Action — just allowing for different instantiations of entities.

#[account]
pub struct Entity {
    pub components: Vec<SerializedComponents>
}

pub struct SerializedComponent{
    pub component_key: Pubkey,
    pub max_size: u64,
    pub data: Vec<u8>,
}

The Registry:

The Registry Program is basically a governance contract. It keeps track of:

  • Registered Components by their Schema URL.
  • Registered Actions that can modify a given Component for a given Registry Instance.
  • The ability to create new instances of the Registry.

For example, it might say that only an admin is allowed to create new instances of the Registry, or it might give that authority up to a DAO.

Same with any components that are registered with it. For example, let’s say for given Game X, there exists a Move Action that lets players move pieces from one tile to another at a speed of 1 tile per second. Another team comes along to create “Portals” in this Registry that allow for faster travel. To allow the Portal Action to be able to modify the “Location” component on Units, requires the governance of the Registry to vote on if this is a change in the rules of the Registry they allow. They might allow it for a specific Registry Instance (you can use it on the “Portals Server” but not on the “Hardcore Server”) for example.

The update authority on components is the Registry, since Actions only submit their proposed changes to the Registry, which then checks governance and then submits the changes to the Core to modify the entity. This crucially means that Actions don’t need to be on-chain games. They can be off-chain gaming infra, like Oracles, which submit changes to an on-chain asset layer that’s controlled by the Game DAO.

#[account]
pub struct ActionBundleRegistration{
    pub system: Pubkey,
    pub instance: u64,
    pub components: Vec<Pubkey>, //PDA of the Component Schema
}

The Action Bundles:

Actions are on-chain or off-chain code that is capable of:

  • Reading Entity PDA & deserializing the components they find valuable.
  • Modifying and submitting a changed serialized component (or a set of components) back to the Registry to be updated with the entity.

The application-specific Actions code allows for “layers” of games. For example, there might exist “Objective: King of the Hill” and “Objective: Kills” Actions. From these two Actions, three possible games could be played. A Registry instance could be instantiated that allows only the first Action, the second Action, or both to be active and allow changes to components.

mod ActionBundle {
	pub fn move_troops() -> Result<()> {..}
	pub fn capture_points() -> Result<()> {..}
	..
}

Benefits of ARC for On-Chain Games

ARC has several benefits for fully on-chain games (FOC) and on-chain assets (OCA), including:

  • Backwards compatibility on schema changes.
  • Because entities can hold dynamic components, you could maintain both v1 and v2 of a component.
  • This allows older applications to query and not lose operational support.
  • Efficiency - Entities are only as big as they need to be thanks to their size being determined by the components they have.
  • Repeatability - The same implementation can be used across ecosystems fairly easily because the base implementation is very simple.
  • Familiarity - web2 gaming companies are more familiar with this framework.
  • Modularity - Adding new properties/behaviors as requirements change is modular.
  • Extensibility - On-chain asset layer is useful for both hybrid games with off-chain oracles that change state for entities and fully on-chain games that read and modify state.
  • Cross-chain accessibility - A simple cross-chain serialization framework and cross-chain identity framework can ease portability to other chains. More on this in future articles.

Conclusion

Overall, ARC is a framework for managing a game’s on-chain asset layer that supports fully on-chain games and those that leverage on-chain assets. This architecture offers scalability, as volume and interdependency of game assets increase and avoid technical debt that may come with an OOP-based approach. In future articles, we will dive deeper into the usage of an ARC-based on-chain games backend and explore other infrastructure that is required to complete the stack.

Special thanks to Joe Howarth, Ben Huan, Anirudh Suresh and many others for valuable feedback!

Share

Stay up to date with the latest from Jump_

More articles

SAFU: Creating a Standard for Whitehats
SAFU: Creating a Standard for Whitehats

Whitehats and DeFi protocols need a shared understanding of security policy. We propose the SAFU - Simple Arrangement for Funding Upload - as a versatile and credible way to let whitehats know what to...

Oct 24 2022 _ 17 min

Share

Disclaimer

The information on this website and on the Brick by Brick podcast or Ship Show Twitter spaces is provided for informational, educational, and entertainment purposes only.  This information is not intended to be and does not constitute financial advice, investment advice, trading advice, or any other type of advice.  You should not make any decision – financial, investment, trading or otherwise – based on any of the information presented here without undertaking your own due diligence and consulting with a financial adviser.  Trading, including that of digital assets or cryptocurrency, has potential rewards as well as potential risks involved. Trading may not be suitable for all individuals. Recordings of podcast episodes or Twitter spaces events may be used in the future.

Building_
Terms of Use_Privacy Policy_Disclaimers_

© 2024 Jump Crypto. All Rights Reserved.

Jump Crypto does not operate any business lines that accept funds from external investors. Any person, company, or app purporting to accept external investor funds on behalf of Jump Crypto is fraudulent.