-
Notifications
You must be signed in to change notification settings - Fork 0
Developer Integration Tutorial
This guide targets UBS 2.0.0, Minecraft 1.21.1, NeoForge, and Java 21.
- Mod ID:
ultimatebankingsystem - Group:
net.austizz.ultimatebankingsystem - Artifact:
ultimatebankingsystem - API version:
2.0.0
For a local jar:
repositories {
flatDir { dirs "libs" }
}
dependencies {
compileOnly name: "ultimatebankingsystem-2.0.0"
localRuntime name: "ultimatebankingsystem-2.0.0"
}For local Maven publication, run gradlew.bat publishToMavenLocal in UBS and add mavenLocal() plus:
compileOnly "net.austizz.ultimatebankingsystem:ultimatebankingsystem:2.0.0"
localRuntime "net.austizz.ultimatebankingsystem:ultimatebankingsystem:2.0.0"Do not shade or jarJar UBS.
Required integration:
[[dependencies.yourmod]]
modId="ultimatebankingsystem"
type="required"
versionRange="[2.0.0,)"
ordering="AFTER"
side="BOTH"For optional integration, use type="optional" and isolate all UBS-linked classes until the mod is present.
if (!ModList.get().isLoaded("ultimatebankingsystem")) {
return;
}UltimateBankingApi finance = UltimateBankingApiProvider.get();
UltimateServerApi server = UltimateBankingApiProvider.server();
UltimateBankManagementApi banks = UltimateBankingApiProvider.banks();
UltimateShopManagementApi shops = UltimateBankingApiProvider.shops();
UltimateHeistApi heists = UltimateBankingApiProvider.heists();At server startup, isAvailable() can be false until the world and Central Bank data are ready.
Run on the server thread:
ApiTransactionResult result = finance.transfer(
buyerAccountId,
sellerAccountId,
new BigDecimal("249.95"),
"AUCTION:" + auctionId
);
if (!result.success()) {
// Show result.reason(); do not apply the sale.
}Use unique, meaningful references for auditability and idempotency in your own system.
if (finance.playerOwnsAnyShop(playerId)) {
List<UUID> shopIds = finance.getPlayerOwnedShopIds(playerId);
}
if (banks.playerOwnsAnyBank(playerId)) {
List<ApiBankManagementSnapshot> owned = banks.getOwnedBanks(playerId);
}
boolean canManage = shops.playerCanManageShop(playerId, shopId);
boolean canBuild = shops.playerCanBuildInShop(playerId, shopId);Use management APIs when you need full snapshots; root finance helpers are intended for lightweight compatibility checks.
ApiManagementResult created = shops.createShop(ownerId, "North Market", "RETAIL");
if (!created.success()) {
// owner may be offline, at capacity, or validation may have failed
}
shops.setOpeningHours(ownerId, shopId, "ALL|09:00|21:00");
shops.setParticipantRole(ownerId, shopId, employeeId, "MANAGER");Never assume role strings. Read getSupportedParticipantRoles() and shop types from getSupportedShopTypes().
banks.getBank(bankId).ifPresent(bank -> {
BigDecimal deposits = bank.totalDeposits();
boolean attacked = bank.underAttack();
int readyVaults = bank.readyVaultCount();
});
ApiSafeDepositSetupSnapshot setup = banks.getSafeDepositSetup(bankId);
if (!setup.enabled()) {
setup.missingRequirements().forEach(logger::warn);
}Safe Access changes and rates still require an authorized actor ID.
Optional<ApiHeistSessionSnapshot> current = heists.getPlayerSession(playerId);
long cooldownMs = heists.getPlayerCooldownRemainingMillis(playerId);
ApiManagementResult ready = heists.setReady(playerId, true);World target scans and all actions belong on the server thread. Do not use these methods from client render code.
@SubscribeEvent
public static void onHeist(HeistLifecycleEvent event) {
if (event.stage() == HeistLifecycleEvent.Stage.ALARMED) {
// Trigger your own server-side security integration.
}
}Register the listener on NeoForge.EVENT_BUS.
Implement HeistLootValueProvider, then:
HeistLootValueRegistry.register(provider);Return a value only for stacks your mod owns. Let other providers or UBS handle unknown stacks.
For modded doors, implement HeistDoorAdapter and register it with HeistDoorAdapterRegistry.
finance.sendNotification(playerId,
ApiNotificationRequest.security("Vault access was denied")
.source("Your Security Mod")
.channel("security")
.priority(ApiNotificationPriority.HIGH)
.build());Use stable IDs for progress/state replacement and channels for scoped cleanup. Use legacy alerts only when maintaining an older integration.
ApiShopPriceStatistics prices = finance.getItemShopPriceStatistics(
itemStack,
ApiShopPriceScope.REGULAR
);
if (prices.available()) {
long fairValueCents = prices.medianPriceCents();
}Median is usually safer for player markets; average is also exposed when your design explicitly needs it.
When an asynchronous service needs UBS data, schedule the call:
minecraftServer.execute(() -> {
ApiManagementResult result = shops.renameShop(actorId, shopId, newName);
// Return the result to your async system after this block.
});Do not call mutations or live target scans directly from HTTP threads, database pools, render threads, or arbitrary executors.
- Treat empty
Optionalandsuccess=falseas expected outcomes. - Show
reason/messageto operators where appropriate. - Do not retry financial mutations blindly.
- Re-fetch snapshots after a successful mutation.
- Never edit UBS saved NBT to simulate an API operation.
Full method and record reference: Developer API.