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:
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.
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. |