Milesoft Games SDKs (games-sdk & game-sdk)

1. Overview

The Milesoft Games framework provides standard SDK clients and callback contracts to manage progression, leaderboards, economies, daily tasks, multiplayer challenges, and AI simulation. To facilitate integration, two distinct SDK libraries are provided:

  1. games-sdk (Plural): An outbound client library used by game applications to communicate with the centralized Games Engine endpoints. It manages player stamina energy, currencies/materials/actives/passives inventory, multiplayer challenges, daily tasks, and general gameplay metrics tracking.
  2. game-sdk (Singular): An inbound callback contract that game applications must implement to support AI player gameplay simulation. When the platform schedules or manually activates an AI bot session, the Games Engine uses the CallbackClient from game-sdk to dispatch requests to the downstream game application's callback endpoints to spawn puzzles and evaluate attempt outcomes.

2. Initialization & Setup

2.1 Dependency Installation

The games-sdk and game-sdk packages are hosted in our secure Google Cloud Artifact Registry repository.

To consume these packages in your Spring Boot application, apply the Google Cloud Artifact Registry plugin and declare our secure repository in your build.gradle:

plugins {
    id "com.google.cloud.artifactregistry.gradle-plugin" version "2.2.5"
}

repositories {
    mavenCentral()
    maven { url "artifactregistry://us-west2-maven.pkg.dev/milesoft-repo/repo-maven" }
}

dependencies {
    // Plural client SDK for outbound operations to games-api
    implementation "io.milesoft:games-sdk:2.0.1"

    // Singular contract SDK for inbound callback endpoints implementation
    implementation "io.milesoft:game-sdk:2.0.1"
}

2.2 Central Spring Boot Configuration (games-sdk)

Configure beans to manage outbound operations to the central Games Engine.

import io.milesoft.clients.PlatformClient;
import io.milesoft.clients.strategy.PlatformTokenProvider;
import io.milesoft.games.client.v2.CampaignClient;
import io.milesoft.games.client.v2.ChallengeClient;
import io.milesoft.games.client.v2.DailyClient;
import io.milesoft.games.client.v2.EnergyClient;
import io.milesoft.games.client.v2.GameClient;
import io.milesoft.games.client.v2.InventoryClient;
import io.milesoft.games.client.v2.LeaderBoardClient;
import io.milesoft.games.client.v2.UsageClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GamesSdkConfig {

    private final EnergyClient energyClient;
    private final InventoryClient inventoryClient;
    private final DailyClient dailyClient;
    private final CampaignClient campaignClient;
    private final GameClient gameClient;
    private final LeaderBoardClient leaderBoardClient;
    private final ChallengeClient challengeClient;
    private final UsageClient usageClient;

    @Autowired
    public GamesSdkConfig(PlatformClient platformClient,
                          @Value("${milesoft.games.baseUrl}") String baseUrl) {

        PlatformTokenProvider tokenProvider = new PlatformTokenProvider(platformClient);

        this.energyClient = new EnergyClient(baseUrl, tokenProvider);
        this.inventoryClient = new InventoryClient(baseUrl, tokenProvider);
        this.dailyClient = new DailyClient(baseUrl, tokenProvider);
        this.campaignClient = new CampaignClient(baseUrl, tokenProvider);
        this.gameClient = new GameClient(baseUrl, tokenProvider);
        this.leaderBoardClient = new LeaderBoardClient(baseUrl, tokenProvider);
        this.challengeClient = new ChallengeClient(baseUrl, tokenProvider);
        this.usageClient = new UsageClient(baseUrl, tokenProvider);
    }

    @Bean
    public EnergyClient energyClient() { return energyClient; }

    @Bean
    public InventoryClient inventoryClient() { return inventoryClient; }

    @Bean
    public DailyClient dailyClient() { return dailyClient; }

    @Bean
    public CampaignClient campaignClient() { return campaignClient; }

    @Bean
    public GameClient gameClient() { return gameClient; }

    @Bean
    public LeaderBoardClient leaderBoardClient() { return leaderBoardClient; }

    @Bean
    public ChallengeClient challengeClient() { return challengeClient; }

    @Bean
    public UsageClient usageClient() { return usageClient; }
}

3. Core Outbound SDK Clients (games-sdk)

Programmatic execution is managed across logical clients designed to completely abstract the underlying REST boundaries.

3.1 CampaignClient

Manages standard multi-tier player single-player stage campaign progression.

  • Campaign find(Actor actor): Retrieves the active player's progression state.
  • Campaign completeLevel(CompleteCampaignLevel payload, Actor actor): Records stage completion.
  • Campaign ascend(AscendCampaign payload, Actor actor): Resets standard progression to ascend to higher difficulty scales.

3.2 EnergyClient

Tracks stamina replenishment pools.

  • Energy find(Actor actor): Retrieves player energy levels.
  • Energy decrement(SaveEnergy payload, Actor actor): Deducts player stamina energy.
  • Energy increment(SaveEnergy payload, Actor actor): Restores player energy.

3.3 LeaderBoardClient

Monitors competitive standings.

  • LeaderBoards find(Actor actor): Fetches active competitive leaderboards.

3.4 InventoryClient

Administers gold/premium balances, material reserves, actives, passives, and timed technology research.

  • Inventory find(Actor actor): Retrieves player asset inventory.
  • Inventory transaction(Transaction payload, Actor actor): Atomic multi-step balances modification (deduct currencies + unlock upgrades).
  • Inventory acquire(Acquire payload, Actor actor): Adds specific item assets.
  • Inventory spend(Spend payload, Actor actor): Spends/consumes inventory assets.
  • Inventory expirePassive(ExpirePassive payload, Actor actor): Terminates expired temporary booster assets.
  • Inventory beginResearch(BeginResearch payload, Actor actor): Registers timed technology upgrades.
  • Inventory completeResearchEarly(CompleteResearchEarly payload, Actor actor): Instantly upgrades technologies.
  • Inventory collectPatrol(CollectPatrol payload, Actor actor): Claims passive earnings gathered over idle periods.

3.5 ChallengeClient

Supports lobby-based multiplayer challenges.

  • Challenges list(Actor actor): Lists pending and active multiplayer challenges.
  • Challenges loadBulk(Ids payload, Actor actor): Batch resolves challenges.
  • Challenge create(CreateChallenge payload, Actor actor): Creates custom challenges.
  • Challenge join(String challengeId, Actor actor): Registers players into lobby slots.
  • void dismissBulk(ChallengeIds payload, Actor actor): Dismisses completed challenges.
  • CompletedChallenge complete(String challengeId, CompleteGame payload, Actor actor): Submits round completions.

3.6 DailyClient

Maintains daily quests.

  • Daily find(Actor actor): Gets active quests.
  • TaskResult complete(CompleteTask payload, Actor actor): Records completions.
  • TaskResult completeBulk(BulkTasks payload, Actor actor): Records batch completions.

3.7 GameClient

Logs overall play histories and statistics.

  • Games find(Actor actor): Retrieves historical stats.
  • Game completeGame(CompleteGame payload, Actor actor): Saves completed round scores.
  • Game importHistory(ImportGame payload, Actor actor): Migrates historic game structures.

3.8 UsageClient

Locks functional features to regulatory user-wide rate limits.

  • Usage find(Actor actor): Returns limits usage profiles.
  • Usage record(RecordUsage payload, Actor actor): Triggers rate usage.
  • Usage recordBulk(BulkUsage payload, Actor actor): Triggers batch rate usage.

4. Inbound Callback Contract (game-sdk)

Downstream game applications (such as your game application) must expose secure REST endpoints specified by the game-sdk callback contract to enable the central Games Engine simulation loop to trigger AI bot actions.

4.1 Downstream Application Implementation Example

The downstream application registers a standard rest controller to resolve bot attempt and puzzle requests dispatched by the Games Engine via CallbackClient.

import io.milesoft.game.client.v2.dto.CreateGame;
import io.milesoft.game.client.v2.dto.Game;
import io.milesoft.game.client.v2.dto.GameAttempt;
import io.milesoft.game.client.v2.dto.GameScore;
import io.milesoft.game.client.v2.transformers.GameScoreDtoTransformer;
import your.game.services.GameService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.mapstruct.factory.Mappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.util.Map;

@RestController
@RequestMapping("/api/v2/callback")
public class CallbackController {

    private final GameService gameService;
    private final GameScoreDtoTransformer gameScoreDtoTransformer;

    @Autowired
    public CallbackController(GameService gameService) {
        this.gameService = gameService;
        this.gameScoreDtoTransformer = Mappers.getMapper(GameScoreDtoTransformer.class);
    }

    /**
     * Called by the Games Engine (via CallbackClient) to score a simulated bot session.
     */
    @RequestMapping(path = "/game/attemptGame", method = RequestMethod.POST,
        consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public GameScore attemptGame(@RequestBody @Valid @NotNull GameAttempt request) {
        io.milesoft.game.domain.GameScore result = gameService.attemptGame(
            request.getDifficulty(), 
            request.getSkill(), 
            request.getElapsed()
        );
        return gameScoreDtoTransformer.toDto(result);
    }

    /**
     * Called by the Games Engine (via CallbackClient) to generate a game puzzle configuration/seed.
     */
    @RequestMapping(path = "/game/createGame", method = RequestMethod.POST,
        consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public Game createGame(@RequestBody @Valid @NotNull CreateGame request) {
        Map<String, Object> gameData = gameService.createGame(request.getDifficulty());
        Game response = new Game();
        response.setData(gameData);
        return response;
    }
}

4.2 Securing the Callback Endpoints

To prevent unauthorized entities from triggering simulated game completion attempts or arbitrarily generating game configurations, the downstream game application must strictly secure all endpoints under the /api/v2/callback/** path.

In the Milesoft ecosystem, system-to-system microservice communication is secured via OAuth/JWT tokens representing platform identities. The Games Engine service executes callbacks acting under the ROBOT authority. Consequently, the game application's security configuration (typically extending AbstractSecurityConfig or configuring Spring Security) must restrict access to these paths accordingly.

Spring Security Configuration Example

Below is an example of restricting the callback paths to the ROBOT role inside the game application's Spring Security config:

import static io.milesoft.stack.constants.RoleConstants.ROBOT;
import static io.milesoft.stack.constants.RoleConstants.USER;

import io.milesoft.app.config.AbstractSecurityConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends AbstractSecurityConfig {

    @Override
    protected void customize(
        AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry customizer) {

        customizer
            // Secure all callback endpoints to require the ROBOT authority
            .requestMatchers("/api/v2/callback/**").hasAuthority(ROBOT)
            
            // Standard user endpoints (such as game, challenge, inventory, etc.)
            .requestMatchers("/api/v2/game/**").hasAuthority(USER)
            .requestMatchers("/api/v2/inventory/**").hasAuthority(USER)
            .requestMatchers("/api/v2/**").authenticated();
    }
}

This ensures that only authorized platform actors, like the scheduled Games Engine simulation runner, can execute these callback endpoints.


5. Code Examples

5.1 Submitting Campaign Progress

import io.milesoft.games.client.v2.CampaignClient;
import io.milesoft.games.client.v2.dto.Campaign;
import io.milesoft.games.client.v2.dto.CampaignLevelAttempt;
import io.milesoft.games.client.v2.dto.CompleteCampaignLevel;
import io.milesoft.primitives.actor.Actor;
import org.springframework.stereotype.Service;
import java.time.ZonedDateTime;

@Service
public class GameProgressionService {

    private final CampaignClient campaignClient;

    public GameProgressionService(CampaignClient campaignClient) {
        this.campaignClient = campaignClient;
    }

    public void saveUserStageCompletion(Actor actor, int stageId, long score, int stars) {
        // Construct progression details
        CompleteCampaignLevel completion = new CompleteCampaignLevel();
        completion.setId(stageId);

        CampaignLevelAttempt attempt = new CampaignLevelAttempt();
        attempt.setScore(score);
        attempt.setStars(stars);
        attempt.setTimestamp(ZonedDateTime.now());
        
        completion.setAttempt(attempt);

        // Execute SDK request
        Campaign updatedCampaign = campaignClient.completeLevel(completion, actor);
        System.out.println("Progression saved! Total campaign ascensions: " + updatedCampaign.getAscensions());
    }
}

6. SDK Data Transfer Objects (DTOs)

Campaign

Field Type Description / Constraints
levels List<CampaignLevel> List of level states. Required.
ascensions Integer Number of times progression was reset for higher-level scaling. Required.
ascended ZonedDateTime Timestamp of the last ascension.
metadata Map<String, Object> Key-value pairs for arbitrary campaign metadata.
created ZonedDateTime Record creation timestamp. Required.
updated ZonedDateTime Record last update timestamp. Required.

CampaignLevel

Field Type Description / Constraints
id Integer Range: EASY_START (0) to INSANE_STOP (99). Required.
best CampaignLevelAttempt Record of the best attempt. Required.
ever CampaignLevelAttempt Record of historical attempt details. Required.
attempts Integer Total attempts on this stage. Required / Min(0).
metadata Map<String, Object> Optional progression level metadata.
created ZonedDateTime Record creation timestamp. Required.
updated ZonedDateTime Record last update timestamp. Required.

CampaignLevelAttempt

Field Type Description / Constraints
stars Integer Range: 0 to 3. Required.
score Long High score attained. Required / Min(0).
timestamp ZonedDateTime Time the level attempt was recorded. Required.

Energy

Field Type Description / Constraints
amount Integer Current user stamina energy pool. Required / Min(0).
created ZonedDateTime Creation timestamp. Required.
updated ZonedDateTime Last energy modification or generation timestamp. Required.

SaveEnergy

Field Type Description / Constraints
amount Integer Energy amount to add or subtract. Required / Min(1).

Inventory

Field Type Description / Constraints
currencies Map<String, Long> Balances of distinct game currencies (e.g., gold, gems). Required.
materials Map<String, Long> Balances of materials. Required.
actives Map<String, Long> Count of active inventory items. Required.
passives Map<String, ZonedDateTime> Passive booster items mapped to their active expiration times. Required.
researchers Integer Active research slots/units. Required / Min(0).
technologies Map<String, Technology> Levels and research timers for technologies. Required.
investigators List<ZonedDateTime> Busy investigators list showing when they return. Required.
patrolStarted ZonedDateTime Time passive patrol idle earning started.
created ZonedDateTime Profile creation timestamp. Required.
updated ZonedDateTime Inventory state last updated. Required.

Technology

Field Type Description / Constraints
level Integer Level of technology item. Required / Min(0).
researchUntil ZonedDateTime Tech upgrade completion timer.
created ZonedDateTime Creation timestamp. Required.
updated ZonedDateTime Last tech upgrade timestamp. Required.

Daily

Field Type Description / Constraints
completedTasks List<String> Identifiers of completed daily goals. Required.
created ZonedDateTime Creation timestamp.
updated ZonedDateTime Update timestamp.

CompleteTask

Field Type Description / Constraints
task String Target quest identifier. Required / Not Blank.
reward Acquire Assets granted upon completion. Required.

Acquire

Field Type Description / Constraints
researchers Integer Number of slots to add. Min(0).
investigators Integer Number of slots to add. Min(0).
currencies Map<String, Long> Currencies to add.
materials Map<String, Long> Materials to add.
actives Map<String, Long> Active consumables to add.
passives Map<String, Long> Passive items to add.

Spend

Field Type Description / Constraints
currencies Map<String, Long> Currencies to deduct.
materials Map<String, Long> Materials to deduct.
actives Map<String, Long> Active consumables to deduct.

Game

Field Type Description / Constraints
type GameType Category enum of the game. Required.
difficulty Difficulty Difficulty level enum.
history GameHistory History statistics of this game type.
created ZonedDateTime Creation timestamp. Required.
updated ZonedDateTime Last update timestamp. Required.

GameHistory

Field Type Description / Constraints
best GamePlayed Details of the best performance.
last GamePlayed Details of the most recent performance.
median GamePlayed Details of standard average performance.
attempts Integer Total play attempts. Required / Min(0).
stars Integer Accumulated stars count. Required / Min(0).

GamePlayed

Field Type Description / Constraints
rounds List<GameRound> Specific rounds of a game play session. Required.
elapsed Long Total play duration in milliseconds. Min(0).
created ZonedDateTime Record timestamp. Required.

GameRound

Field Type Description / Constraints
stars Integer Range: 0 to 3. Required.
score Long Earned score. Required / Min(0).
penalty Long Accumulated time penalties. Required / Min(0).

CompleteGame

Field Type Description / Constraints
type GameType Category enum of the game. Required.
difficulty Difficulty Difficulty level enum.
rounds List<GameRound> Rounds played. Required.
elapsed Long Session duration in milliseconds. Min(0).

Challenge

Field Type Description / Constraints
id String Unique UUID identifier. Required / Not Blank.
difficulty Difficulty Target challenge difficulty.
game Map<String, Object> Specific game seed/puzzle layout data. Required.
source Player Initiating player details.
targets List<Player> Target players invited to this challenge.
dismisseds List<Player> Players who declined the challenge.
global Boolean If true, accessible by any user globally. Required.
results List<LeaderBoardResult> Leaderboard standings of users in this challenge.
expires ZonedDateTime Time when challenge expires.
created ZonedDateTime Challenge creation time. Required.
updated ZonedDateTime Challenge updated time. Required.

Player

Field Type Description / Constraints
id String Unique user identifier.
alias String Display username or bot handle.
imageUrl String Profile photo path.

LeaderBoardResult

Field Type Description / Constraints
player Player Standing owner. Required.
data Map<String, Object> Statistics details (e.g., score, total elapsed time). Required.

LeaderBoard

Field Type Description / Constraints
type LeaderBoardType Scope of leaderboard (e.g., daily, weekly). Required.
difficulty Difficulty Optional leaderboard difficulty level.
results List<LeaderBoardResult> High-scores standings list. Required.
created ZonedDateTime Generation timestamp. Required.
updated ZonedDateTime High score update timestamp. Required.

Ai

Field Type Description / Constraints
id String Bot UUID. Required / Not Blank.
appId String Tenant Application ID context. Required.
accountId String Client-system account context. Required.
player Player Display player profile. Required.
skill Skill Solver capability scaling level. Required.
activateAt ZonedDateTime Next planned bot play execution. Required.
created ZonedDateTime Record creation time. Required.
updated ZonedDateTime Configuration modification time. Required.

CampaignAttempt (game-sdk DTO)

Field Type Description / Constraints
levelId Integer The campaign level ID being attempted. Required / Min(1).
skill Skill The solver skill tier being evaluated. Required.
outcome Outcome The outcome of the stage challenge. Required.
stars Integer Stars awarded. Min(0) / Max(3).

CampaignScore (game-sdk DTO)

Field Type Description / Constraints
levelId Integer Level completed. Required / Min(1).
stars Integer Stars earned. Range: 0 to 3. Required.
score Long High score attained. Required / Min(0).

GameAttempt (game-sdk DTO)

Field Type Description / Constraints
gameType GameType Session play style. Required.
difficulty Difficulty Attempted difficulty setting.
skill Skill Evaluated skill classification. Required.
outcome Outcome Round execution outcome. Required.
stars Integer Stars earned. Min(0) / Max(3).
elapsed Long Time elapsed during session. Min(0).

GameScore (game-sdk DTO)

Field Type Description / Constraints
type GameType Evaluated game session type. Required.
difficulty Difficulty Active session difficulty.
rounds List<RoundScore> List of individual round scores. Required.

RoundScore (game-sdk DTO)

Field Type Description / Constraints
stars Integer Stars earned in round. Range: 0 to 3. Required.
score Long Points scored. Required / Min(0).
penalty Long Penalty seconds/points incurred. Required / Min(0).

CreateGame (game-sdk DTO)

Field Type Description / Constraints
difficulty Difficulty Requested initial difficulty.

Callback Game (game-sdk DTO)

Field Type Description / Constraints
data Map<String, Object> Seed or session layout metadata. Required.