### Setup SteamApps and PICS Callbacks Source: https://context7.com/longi94/javasteam/llms.txt Initializes the SteamApps handler and subscribes to PICSProductInfoCallback and LicenseListCallback. Ensure SteamClient and CallbackManager are properly initialized before calling setup. ```java import in.dragonbra.javasteam.steam.handlers.steamapps.SteamApps; import in.dragonbra.javasteam.steam.handlers.steamapps.PICSRequest; import in.dragonbra.javasteam.steam.handlers.steamapps.callback.PICSProductInfoCallback; import in.dragonbra.javasteam.steam.handlers.steamapps.callback.LicenseListCallback; import in.dragonbra.javasteam.types.KeyValue; public class ProductInformation { private SteamClient steamClient; private SteamApps steamApps; private CallbackManager manager; public void setup() { steamApps = steamClient.getHandler(SteamApps.class); manager.subscribe(PICSProductInfoCallback.class, this::onPicsProduct); manager.subscribe(LicenseListCallback.class, this::onLicenseList); } private void onLoggedOn() { // Request product info for specific app IDs // HellDivers 2 = 553850, Team Fortress 2 = 440, CS2 = 730 steamApps.picsGetProductInfo(new PICSRequest(553850), null); // Request multiple apps at once // List apps = List.of(new PICSRequest(440), new PICSRequest(730)); // steamApps.picsGetProductInfo(apps, null); } private void onPicsProduct(PICSProductInfoCallback callback) { System.out.println("Received product info for " + callback.getApps().size() + " apps"); for (var entry : callback.getApps().entrySet()) { int appId = entry.getKey(); var appInfo = entry.getValue(); System.out.println("App ID: " + appId); System.out.println("Change Number: " + appInfo.getChangeNumber()); // Parse KeyValue data KeyValue kv = appInfo.getKeyValues(); printKeyValue(kv, 0); } } private void onLicenseList(LicenseListCallback callback) { System.out.println("You own " + callback.getLicenseList().size() + " licenses"); for (var license : callback.getLicenseList()) { System.out.println("Package: " + license.getPackageID() + ", Type: " + license.getLicenseType()); } } private void printKeyValue(KeyValue kv, int depth) { String indent = " ".repeat(depth); if (kv.getChildren().isEmpty()) { System.out.println(indent + kv.getName() + ": " + kv.getValue()); } else { System.out.println(indent + kv.getName() + ":"); for (KeyValue child : kv.getChildren()) { printKeyValue(child, depth + 1); } } } } ``` -------------------------------- ### Install JavaSteam via Build Tools Source: https://context7.com/longi94/javasteam/llms.txt Include the library and required cryptography dependencies in your project configuration. ```groovy // Gradle repositories { mavenCentral() } dependencies { implementation 'in.dragonbra:javasteam:1.8.0' implementation 'org.bouncycastle:bcprov-jdk18on:1.78' // Optional: For content downloading implementation 'org.tukaani:xz:1.9' implementation 'com.github.luben:zstd-jni:1.5.5-11' // Optional: For working with protobufs directly implementation 'com.google.protobuf:protobuf-java:4.27.0' } ``` ```xml in.dragonbra javasteam 1.8.0 org.bouncycastle bcprov-jdk18on 1.78 ``` -------------------------------- ### Install Unlimited Strength Jurisdiction Policy Files Source: https://github.com/longi94/javasteam/wiki/Download Resolve 'Illegal key size or default parameters' exceptions by installing the Unlimited Strength Jurisdiction Policy Files. Place the downloaded files in the `${java.home}/jre/lib/security/` directory. ```text ${java.home}/jre/lib/security/ ``` -------------------------------- ### Implement ContentDownloaderExample for Steam content Source: https://context7.com/longi94/javasteam/llms.txt This example demonstrates how to use DepotDownloader by implementing IDownloadListener to handle download events and configuring an AppItem for downloading a specific Steam application. ```java import in.dragonbra.javasteam.depotdownloader.DepotDownloader; import in.dragonbra.javasteam.depotdownloader.IDownloadListener; import in.dragonbra.javasteam.depotdownloader.data.*; import in.dragonbra.javasteam.steam.handlers.steamapps.License; import in.dragonbra.javasteam.steam.handlers.steamapps.callback.LicenseListCallback; import java.util.List; public class ContentDownloaderExample implements IDownloadListener { private SteamClient steamClient; private List licenseList; private void onLicenseList(LicenseListCallback callback) { if (callback.getResult() != EResult.OK) { System.err.println("Failed to get licenses"); return; } licenseList = callback.getLicenseList(); System.out.println("Received " + licenseList.size() + " licenses"); // Start downloading downloadGame(); } private void downloadGame() { // DepotDownloader is Closeable try (var depotDownloader = new DepotDownloader(steamClient, licenseList, true)) { // Add download listener depotDownloader.addListener(this); // Configure app download var appItem = new AppItem( /* appId */ 1303350, // Rocky Mayhem (free game) /* installToGameNameDirectory */ true, /* installDirectory */ "steamapps", /* branch */ "public", /* branchPassword */ "", /* downloadAllPlatforms */ false, /* os */ "windows", /* downloadAllArchs */ false, /* osArch */ "64", /* downloadAllLanguages */ false, /* language */ "english", /* lowViolence */ false, /* depot */ List.of(), // Empty = all depots /* manifest */ List.of(), // Empty = latest manifest /* verify */ false, /* downloadManifestOnly */ false ); // Add to download queue depotDownloader.add(appItem); // Can also download workshop items // var ugcItem = new UgcItem(appId, ugcId, false, null, false, false); // depotDownloader.add(ugcItem); // Can also download pub files // var pubItem = new PubFileItem(appId, pubFileId, false, null, false, false); // depotDownloader.add(pubItem); // Signal no more items will be added depotDownloader.finishAdding(); // Wait for downloads to complete (blocking) depotDownloader.awaitCompletion(); depotDownloader.removeListener(this); } finally { System.out.println("Download complete"); } } // IDownloadListener callbacks @Override public void onItemAdded(DownloadItem item) { System.out.println("Queued: App " + item.getAppId()); } @Override public void onDownloadStarted(DownloadItem item) { System.out.println("Started: App " + item.getAppId()); } @Override public void onDownloadCompleted(DownloadItem item) { System.out.println("Completed: App " + item.getAppId()); } @Override public void onDownloadFailed(DownloadItem item, Throwable error) { System.err.println("Failed: App " + item.getAppId() + " - " + error.getMessage()); } @Override public void onStatusUpdate(String message) { System.out.println("Status: " + message); } @Override public void onFileCompleted(int depotId, String fileName, float percentComplete) { System.out.println(String.format("Depot %d: %s (%.1f%%)", depotId, fileName, percentComplete * 100)); } @Override public void onDepotCompleted(int depotId, long compressedBytes, long uncompressedBytes) { System.out.println("Depot " + depotId + " done: " + uncompressedBytes + " bytes uncompressed"); } } ``` -------------------------------- ### Setup SteamFriends Handler and Callbacks Source: https://context7.com/longi94/javasteam/llms.txt Initializes the SteamFriends handler and subscribes to essential friend-related callbacks. Ensure SteamClient and CallbackManager are properly initialized before calling this setup method. ```java import in.dragonbra.javasteam.steam.handlers.steamfriends.SteamFriends; import in.dragonbra.javasteam.steam.handlers.steamfriends.Friend; import in.dragonbra.javasteam.steam.handlers.steamfriends.callback.*; import in.dragonbra.javasteam.steam.handlers.steamuser.callback.AccountInfoCallback; import in.dragonbra.javasteam.enums.EFriendRelationship; import in.dragonbra.javasteam.enums.EPersonaState; import in.dragonbra.javasteam.types.SteamID; public class FriendsManagement { private SteamClient steamClient; private SteamFriends steamFriends; private CallbackManager manager; public void setup() { steamFriends = steamClient.getHandler(SteamFriends.class); // Register friend-related callbacks manager.subscribe(AccountInfoCallback.class, this::onAccountInfo); manager.subscribe(FriendsListCallback.class, this::onFriendsList); manager.subscribe(PersonaStateCallback.class, this::onPersonaState); manager.subscribe(FriendAddedCallback.class, this::onFriendAdded); } private void onAccountInfo(AccountInfoCallback callback) { // Account info received - now we can go online steamFriends.setPersonaState(EPersonaState.Online); // Set custom persona name (optional) // steamFriends.setPersonaName("My Bot Name"); } private void onFriendsList(FriendsListCallback callback) { System.out.println("Friends list received: " + callback.getFriendList().size() + " friends"); for (Friend friend : callback.getFriendList()) { SteamID steamIdFriend = friend.getSteamID(); // Display friend's Steam ID System.out.println("Friend: " + steamIdFriend.render()); // Auto-accept incoming friend requests if (friend.getRelationship() == EFriendRelationship.RequestRecipient) { System.out.println("Accepting friend request from: " + steamIdFriend.render()); steamFriends.addFriend(steamIdFriend); } } // Request persona info for specific users // steamFriends.requestFriendInfo(steamId, EClientPersonaStateFlag.PlayerName); } private void onPersonaState(PersonaStateCallback callback) { // Friend's persona state changed System.out.println("Friend update: " + callback.getName() + " is now " + callback.getState()); } private void onFriendAdded(FriendAddedCallback callback) { System.out.println("New friend added: " + callback.getPersonaName()); } } ``` -------------------------------- ### Generate Project Classes with Gradle Source: https://github.com/longi94/javasteam/wiki/Contributing Run this command to generate Protobufs and SteamLanguage files. Your IDE should recognize the new classes afterward. ```bash ./gradlew generateProto generateSteamLanguage generateProjectVersion generateRpcMethods ``` -------------------------------- ### Establish a SteamClient Connection Source: https://context7.com/longi94/javasteam/llms.txt Initialize the SteamClient, register callbacks for connection events, and process the callback loop. ```java import in.dragonbra.javasteam.steam.steamclient.SteamClient; import in.dragonbra.javasteam.steam.steamclient.callbackmgr.CallbackManager; import in.dragonbra.javasteam.steam.steamclient.callbacks.ConnectedCallback; import in.dragonbra.javasteam.steam.steamclient.callbacks.DisconnectedCallback; import in.dragonbra.javasteam.steam.handlers.steamuser.SteamUser; import in.dragonbra.javasteam.util.log.DefaultLogListener; import in.dragonbra.javasteam.util.log.LogManager; public class BasicConnection { private SteamClient steamClient; private CallbackManager manager; private SteamUser steamUser; private boolean isRunning; public void run() { // Enable logging (optional) LogManager.addListener(new DefaultLogListener()); // Create the SteamClient instance steamClient = new SteamClient(); // Create callback manager to route callbacks to handlers manager = new CallbackManager(steamClient); // Get the SteamUser handler for authentication steamUser = steamClient.getHandler(SteamUser.class); // Register callbacks manager.subscribe(ConnectedCallback.class, this::onConnected); manager.subscribe(DisconnectedCallback.class, this::onDisconnected); isRunning = true; System.out.println("Connecting to Steam..."); // Initiate connection to Steam servers steamClient.connect(); // Main callback processing loop while (isRunning) { manager.runWaitCallbacks(1000L); } } private void onConnected(ConnectedCallback callback) { System.out.println("Connected to Steam!"); // Proceed with authentication... } private void onDisconnected(DisconnectedCallback callback) { System.out.println("Disconnected from Steam. User initiated: " + callback.isUserInitiated()); if (callback.isUserInitiated()) { isRunning = false; } else { // Auto-reconnect after delay try { Thread.sleep(2000L); steamClient.connect(); } catch (InterruptedException e) { e.printStackTrace(); } } } } ``` -------------------------------- ### Implement SteamGameCoordinator Communication in Java Source: https://context7.com/longi94/javasteam/llms.txt Demonstrates how to initialize the handler, notify Steam of game activity, establish a GC connection, and handle incoming messages for CS2. ```java import in.dragonbra.javasteam.steam.handlers.steamgamecoordinator.SteamGameCoordinator; import in.dragonbra.javasteam.steam.handlers.steamgamecoordinator.callback.MessageCallback; import in.dragonbra.javasteam.base.gc.ClientGCMsgProtobuf; import in.dragonbra.javasteam.base.ClientMsgProtobuf; import in.dragonbra.javasteam.enums.EMsg; import in.dragonbra.javasteam.enums.EAccountType; import in.dragonbra.javasteam.enums.EUniverse; import in.dragonbra.javasteam.types.SteamID; import in.dragonbra.javasteam.protobufs.cs.Cstrike15Gcmessages; import in.dragonbra.javasteam.protobufs.cs.GcsdkGcmessages; import in.dragonbra.javasteam.protobufs.cs.Gcsystemmsgs; import in.dragonbra.javasteam.protobufs.steamclient.SteammessagesClientserver; public class GameCoordinatorExample { private SteamClient steamClient; private SteamGameCoordinator steamGameCoordinator; private static final int CS2_APP_ID = 730; public void setup() { steamGameCoordinator = steamClient.getHandler(SteamGameCoordinator.class); manager.subscribe(MessageCallback.class, this::onGCMessage); } private void onLoggedOn() { // Tell Steam we're playing CS2 startPlayingGame(CS2_APP_ID); // Send hello to establish GC connection sendHello(); } private void startPlayingGame(int appId) { var gamesPlayed = new ClientMsgProtobuf( SteammessagesClientserver.CMsgClientGamesPlayed.class, EMsg.ClientGamesPlayed ); gamesPlayed.getBody().addGamesPlayedBuilder().setGameId(appId); steamClient.send(gamesPlayed); } private void sendHello() { var hello = new ClientGCMsgProtobuf( GcsdkGcmessages.CMsgClientHello.class, Gcsystemmsgs.EGCBaseClientMsg.k_EMsgGCClientHello.getNumber() ); hello.getBody().setVersion(2000244); steamGameCoordinator.send(hello, CS2_APP_ID); } private void onGCMessage(MessageCallback callback) { int messageType = callback.getMessage().getMsgType(); System.out.println("GC Message: " + messageType + " from App " + callback.getAppID()); // GC Welcome - we can now send requests if (messageType == Gcsystemmsgs.EGCBaseClientMsg.k_EMsgGCClientWelcome.getNumber()) { System.out.println("GC has welcomed us!"); // Request a player's CS2 profile requestPlayerProfile(76561198386265483L); } // Player profile response if (messageType == Cstrike15Gcmessages.ECsgoGCMsg.k_EMsgGCCStrike15_v2_PlayersProfile.getNumber()) { var response = new ClientGCMsgProtobuf( Cstrike15Gcmessages.CMsgGCCStrike15_v2_PlayersProfile.class, callback.getMessage() ); for (var profile : response.getBody().getAccountProfilesList()) { System.out.println("Account ID: " + profile.getAccountId()); System.out.println("Player Level: " + profile.getPlayerLevel()); } } } private void requestPlayerProfile(long steamId64) { SteamID sid = new SteamID(steamId64); // Validate SteamID if (!sid.isValid() || sid.getAccountUniverse() != EUniverse.Public || sid.getAccountType() != EAccountType.Individual) { System.err.println("Invalid SteamID"); return; } var profileRequest = new ClientGCMsgProtobuf( Cstrike15Gcmessages.CMsgGCCStrike15_v2_ClientRequestPlayersProfile.class, Cstrike15Gcmessages.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientRequestPlayersProfile.getNumber() ); profileRequest.getBody().setAccountId((int) sid.getAccountID()); profileRequest.getBody().setRequestLevel(32); steamGameCoordinator.send(profileRequest, CS2_APP_ID); } } ``` -------------------------------- ### Connect to Steam Servers Source: https://github.com/longi94/javasteam/wiki/Getting-started Initializes a SteamClient instance and initiates the connection process. ```java SteamClient client = new SteamClient(); client.connect(); ``` -------------------------------- ### Configure Logging Source: https://github.com/longi94/javasteam/wiki/Getting-started Sets up a log listener to handle library output, using the default console printer or a custom implementation. ```java LogManager.addListener(new DefaultLogListener()); ``` -------------------------------- ### Create Configured Steam Client Source: https://context7.com/longi94/javasteam/llms.txt Use SteamConfiguration.create to build a custom client configuration. This includes setting protocol types, server list providers, cell IDs, and HTTP clients with custom timeouts. The configured client can then be used to establish a connection. ```java import in.dragonbra.javasteam.steam.steamclient.SteamClient; import in.dragonbra.javasteam.steam.steamclient.configuration.SteamConfiguration; import in.dragonbra.javasteam.steam.discovery.FileServerListProvider; import in.dragonbra.javasteam.networking.steam3.ProtocolTypes; import okhttp3.OkHttpClient; import java.io.File; import java.util.concurrent.TimeUnit; public class ConfiguredClient { public void createConfiguredClient() { // Create custom configuration SteamConfiguration configuration = SteamConfiguration.create(builder -> { // Set connection protocol (TCP, UDP, or WebSocket) builder.withProtocolTypes(ProtocolTypes.TCP); // Use file-based server list for faster reconnections builder.withServerListProvider(new FileServerListProvider(new File("servers.bin"))); // Set cell ID for regional server selection builder.withCellID(1); // Configure custom HTTP client with timeouts builder.withHttpClient( new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build() ); // Set Web API key if needed // builder.withWebAPIKey("YOUR_API_KEY"); }); // Create client with custom configuration SteamClient steamClient = new SteamClient(configuration); // Connect and proceed... steamClient.connect(); } } ``` -------------------------------- ### Execute Build Tasks Source: https://github.com/longi94/javasteam/blob/master/README.md Run Gradle tasks to build the project or generate necessary source files. ```bash ./gradlew build -x signMavenJavaPublication ``` ```bash ./gradlew generateProto generateSteamLanguage generateProjectVersion ``` -------------------------------- ### Retrieve Steam News via WebAPI Source: https://context7.com/longi94/javasteam/llms.txt Demonstrates how to initialize the WebAPI interface for ISteamNews, execute a request for app news, and iterate through the returned KeyValue structure. ```java import in.dragonbra.javasteam.steam.webapi.WebAPI; import in.dragonbra.javasteam.types.KeyValue; import java.util.HashMap; import java.util.Map; public class WebAPIExample { private SteamClient steamClient; private void onLoggedOn() { // Get WebAPI interface for Steam News WebAPI api = steamClient.getConfiguration().getWebAPI("ISteamNews"); try { // Build request parameters Map args = new HashMap<>(); args.put("appid", "440"); // Team Fortress 2 args.put("count", "5"); // Get 5 news items args.put("maxlength", "300"); // Truncate content // Call the API method (version 2) KeyValue result = api.call("GetNewsForApp", 2, args); // Parse the response printKeyValue(result, 0); // Example: Extract specific values KeyValue newsItems = result.get("appnews").get("newsitems"); for (KeyValue item : newsItems.getChildren()) { System.out.println("Title: " + item.get("title").getValue()); System.out.println("URL: " + item.get("url").getValue()); System.out.println("Date: " + item.get("date").getValue()); System.out.println("---"); } } catch (Exception e) { System.err.println("WebAPI call failed: " + e.getMessage()); } } private void printKeyValue(KeyValue kv, int depth) { String indent = " ".repeat(depth); if (kv.getChildren().isEmpty()) { System.out.println(indent + kv.getName() + ": " + kv.getValue()); } else { System.out.println(indent + kv.getName() + ":"); for (KeyValue child : kv.getChildren()) { printKeyValue(child, depth + 1); } } } } ``` -------------------------------- ### Implement Modern Authentication with 2FA Source: https://context7.com/longi94/javasteam/llms.txt Demonstrates the authentication flow using credentials, handling 2FA via a console authenticator, and logging on with a refresh token. ```java import in.dragonbra.javasteam.steam.steamclient.SteamClient; import in.dragonbra.javasteam.steam.steamclient.callbackmgr.CallbackManager; import in.dragonbra.javasteam.steam.steamclient.callbacks.ConnectedCallback; import in.dragonbra.javasteam.steam.handlers.steamuser.SteamUser; import in.dragonbra.javasteam.steam.handlers.steamuser.LogOnDetails; import in.dragonbra.javasteam.steam.handlers.steamuser.callback.LoggedOnCallback; import in.dragonbra.javasteam.steam.authentication.*; import in.dragonbra.javasteam.enums.EResult; public class ModernAuthentication { private SteamClient steamClient; private SteamUser steamUser; private String previouslyStoredGuardData; // Persist this to avoid repeated 2FA private void onConnected(ConnectedCallback callback) { System.out.println("Connected! Starting authentication..."); // Set up authentication details AuthSessionDetails authDetails = new AuthSessionDetails(); authDetails.username = "your_username"; authDetails.password = "your_password"; authDetails.persistentSession = true; // Remember login // Use stored guard data to skip 2FA if available authDetails.guardData = previouslyStoredGuardData; // Use built-in console authenticator for 2FA prompts // Or implement IAuthenticator for custom handling authDetails.authenticator = new UserConsoleAuthenticator(); try { // Begin authentication session CredentialsAuthSession authSession = steamClient .getAuthentication() .beginAuthSessionViaCredentials(authDetails) .get(); // Poll for authentication result (blocks until complete) AuthPollResult pollResponse = authSession.pollingWaitForResult().get(); // Store guard data for future logins if (pollResponse.getNewGuardData() != null) { previouslyStoredGuardData = pollResponse.getNewGuardData(); // Persist this data to skip 2FA next time } // Log on to Steam using the refresh token LogOnDetails details = new LogOnDetails(); details.setUsername(pollResponse.getAccountName()); details.setAccessToken(pollResponse.getRefreshToken()); details.setLoginID(149); // Unique ID for multiple clients steamUser.logOn(details); } catch (AuthenticationException e) { System.err.println("Authentication failed: " + e.getMessage()); } catch (Exception e) { System.err.println("Error: " + e.getMessage()); } } private void onLoggedOn(LoggedOnCallback callback) { if (callback.getResult() == EResult.OK) { System.out.println("Successfully logged in!"); System.out.println("SteamID: " + callback.getClientSteamID().convertToUInt64()); } else { System.out.println("Login failed: " + callback.getResult()); } } } ``` -------------------------------- ### Initialize and Use SteamUnifiedMessages Source: https://context7.com/longi94/javasteam/llms.txt Demonstrates setting up the SteamUnifiedMessages handler, creating a typed service interface, and handling both synchronous service requests and asynchronous notifications. ```java import in.dragonbra.javasteam.steam.handlers.steamunifiedmessages.SteamUnifiedMessages; import in.dragonbra.javasteam.steam.handlers.steamunifiedmessages.callback.ServiceMethodNotification; import in.dragonbra.javasteam.rpc.service.Player; import in.dragonbra.javasteam.rpc.service.FriendMessagesClient; import in.dragonbra.javasteam.protobufs.steamclient.SteammessagesPlayerSteamclient.*; import in.dragonbra.javasteam.protobufs.steamclient.SteammessagesFriendmessagesSteamclient.*; import in.dragonbra.javasteam.enums.EResult; public class UnifiedMessagesExample { private SteamClient steamClient; private SteamUnifiedMessages steamUnifiedMessages; private Player playerService; private CallbackManager manager; public void setup() { steamUnifiedMessages = steamClient.getHandler(SteamUnifiedMessages.class); // Create typed service interface for Player API playerService = steamUnifiedMessages.createService(Player.class); // Subscribe to incoming friend messages manager.subscribeServiceNotification( FriendMessagesClient.class, CFriendMessages_IncomingMessage_Notification.Builder.class, this::onIncomingMessage ); } private void onLoggedOn() { // Request game badge levels using typed service CPlayer_GetGameBadgeLevels_Request request = CPlayer_GetGameBadgeLevels_Request.newBuilder() .setAppid(440) // Team Fortress 2 .build(); try { var response = playerService.getGameBadgeLevels(request).toFuture().get(); if (response.getResult() == EResult.OK) { System.out.println("Player Level: " + response.getBody().getPlayerLevel()); for (var badge : response.getBody().getBadgesList()) { System.out.println("Badge " + badge.getSeries() + ": Level " + badge.getLevel()); } } } catch (Exception e) { System.err.println("Failed to get badges: " + e.getMessage()); } // Alternative: Send message directly without typed service try { var responseAlt = steamUnifiedMessages.sendMessage( CPlayer_GetGameBadgeLevels_Response.Builder.class, "Player.GetGameBadgeLevels#1", // Format: Service.Method#Version request ).toFuture().get(); System.out.println("Alt request player level: " + responseAlt.getBody().getPlayerLevel()); } catch (Exception e) { System.err.println("Alt request failed: " + e.getMessage()); } } private void onIncomingMessage( ServiceMethodNotification notification) { if (notification.getBody().getChatEntryType() == 1) { // Regular message System.out.println("Message received: " + notification.getBody().getMessage()); } else if (notification.getBody().getChatEntryType() == 2) { // Typing indicator System.out.println("Friend is typing..."); } } } ``` -------------------------------- ### Configure Maven Central Repository Source: https://github.com/longi94/javasteam/blob/master/README.md Add the Maven Central repository to your build configuration. ```groovy repositories { mavenCentral() } ``` ```xml central https://repo.maven.apache.org/maven2 ``` -------------------------------- ### Add Snapshot Repository to Build Source: https://github.com/longi94/javasteam/wiki/Download Configure your build tool to include the snapshot repository for JavaSteam. This is necessary for using snapshot versions of the library. ```text https://central.sonatype.com/repository/maven-snapshots/ ``` -------------------------------- ### Search and List Steam Lobbies Source: https://context7.com/longi94/javasteam/llms.txt Demonstrates how to configure lobby filters, execute a search request, and iterate through the results to display lobby metadata and member details. ```java import in.dragonbra.javasteam.steam.handlers.steammatchmaking.SteamMatchmaking; import in.dragonbra.javasteam.steam.handlers.steammatchmaking.*; import in.dragonbra.javasteam.enums.ELobbyComparison; import in.dragonbra.javasteam.enums.ELobbyDistanceFilter; import java.util.List; public class MatchmakingExample { private SteamClient steamClient; private SteamMatchmaking steamMatchmaking; private final int appId = 480; // Spacewar (test app) public void setup() { steamMatchmaking = steamClient.getHandler(SteamMatchmaking.class); } private void onLoggedOn() { try { // Create lobby filters List filters = List.of( // Search worldwide new DistanceFilter(ELobbyDistanceFilter.Worldwide), // Filter by specific metadata new StringFilter("CONMETHOD", "P2P", ELobbyComparison.Equal) // Other filter types: // new NumericalFilter("max_players", 4, ELobbyComparison.EqualToOrGreaterThan) // new SlotsAvailableFilter(1) // new NearValueFilter("skill_rating", 1000) ); // Request up to 20 lobbies matching filters var lobbyListResult = steamMatchmaking.getLobbyList(appId, filters, 20) .toFuture() .get(); System.out.println("Found " + lobbyListResult.getLobbies().size() + " lobbies"); for (var lobby : lobbyListResult.getLobbies()) { System.out.println("Lobby: " + lobby.getSteamID().convertToUInt64()); System.out.println(" Owner: " + lobby.getOwnerSteamID()); System.out.println(" Type: " + lobby.getLobbyType()); System.out.println(" Members: " + lobby.getNumMembers() + "/" + lobby.getMaxMembers()); System.out.println(" Distance: " + lobby.getDistance()); // Print lobby metadata System.out.println(" Metadata:"); lobby.getMetadata().forEach((key, value) -> System.out.println(" " + key + ": " + value)); // Print member info System.out.println(" Members:"); for (var member : lobby.getMembers()) { System.out.println(" " + member.getPersonaName() + " (" + member.getSteamID().convertToUInt64() + ")"); } } } catch (Exception e) { System.err.println("Lobby search failed: " + e.getMessage()); } } } ``` -------------------------------- ### Add JavaSteam Dependency Source: https://github.com/longi94/javasteam/wiki/Download Include the JavaSteam library in your project's dependencies. Specify the release or snapshot version as needed. ```text in.dragonbra:javasteam:x.y.z ``` ```text in.dragonbra:javasteam:x.y.z-SNAPSHOT ``` -------------------------------- ### Implement and Register a Custom Handler in Java Source: https://context7.com/longi94/javasteam/llms.txt Defines a custom handler class to process specific Steam messages and demonstrates how to register it with the SteamClient and subscribe to its callbacks. ```java import in.dragonbra.javasteam.steam.handlers.ClientMsgHandler; import in.dragonbra.javasteam.base.ClientMsgProtobuf; import in.dragonbra.javasteam.base.IPacketMsg; import in.dragonbra.javasteam.enums.EMsg; import in.dragonbra.javasteam.enums.EResult; import in.dragonbra.javasteam.protobufs.steamclient.SteammessagesClientserverLogin.CMsgClientLogonResponse; import in.dragonbra.javasteam.steam.steamclient.callbackmgr.CallbackMsg; // Custom handler extending ClientMsgHandler public class MyCustomHandler extends ClientMsgHandler { // Define custom callback for passing data to user code public static class MyCustomCallback extends CallbackMsg { private final EResult result; private final String customData; public MyCustomCallback(EResult result, String customData) { this.result = result; this.customData = customData; } public EResult getResult() { return result; } public String getCustomData() { return customData; } } // Custom method to send messages public void doSomething() { // Build and send custom message // client.send(someMessage); } @Override public void handleMsg(IPacketMsg packetMsg) { // Handle specific message types switch (packetMsg.getMsgType()) { case ClientLogOnResponse: handleLogonResponse(packetMsg); break; // Add more cases as needed } } private void handleLogonResponse(IPacketMsg packetMsg) { // Wrap packet to access message body ClientMsgProtobuf response = new ClientMsgProtobuf<>(CMsgClientLogonResponse.class, packetMsg); EResult result = EResult.from(response.getBody().getEresult()); // Post callback to user code client.postCallback(new MyCustomCallback(result, "Logon handled by custom handler")); } } // Usage in main application public class CustomHandlerUsage { private SteamClient steamClient; private MyCustomHandler myHandler; private CallbackManager manager; public void setup() { steamClient = new SteamClient(); // Register custom handler steamClient.addHandler(new MyCustomHandler()); manager = new CallbackManager(steamClient); // Get reference to custom handler myHandler = steamClient.getHandler(MyCustomHandler.class); // Subscribe to custom callback manager.subscribe(MyCustomHandler.MyCustomCallback.class, this::onMyCustomCallback); } private void onMyCustomCallback(MyCustomHandler.MyCustomCallback callback) { System.out.println("Custom callback received: " + callback.getResult()); System.out.println("Custom data: " + callback.getCustomData()); } } ``` -------------------------------- ### Add JavaSteam Dependency Source: https://github.com/longi94/javasteam/blob/master/README.md Include the JavaSteam library in your project dependencies. Replace x.y.z with the desired version. ```groovy implementation 'in.dragonbra:javasteam:x.y.z' ``` ```xml in.dragonbra javasteam x.y.z ``` -------------------------------- ### Configure SteamClient Source: https://github.com/longi94/javasteam/wiki/Getting-started Customizes client behavior using SteamConfiguration, such as setting protocol types or server list providers. ```java SteamConfiguration configuration = SteamConfiguration.create(builder -> { builder.setProtocolTypes(ProtocolTypes.TCP); builder.withServerListProvider(new FileServerListProvider(new File("servers.bin"))); }); SteamClient client = new SteamClient(configuration); ``` -------------------------------- ### Configure R8/ProGuard Rules for JavaSteam Source: https://github.com/longi94/javasteam/wiki/Runtimes Include these rules in your ProGuard configuration to prevent R8 from stripping JavaSteam classes during release builds. ```proguard ########### # JAVASTEAM ########### -keep class in.dragonbra.javasteam.** { *; } ``` -------------------------------- ### Configure IntelliJ for Large File Sizes Source: https://github.com/longi94/javasteam/wiki/Contributing Adjust IntelliJ's custom properties to increase the file size limits for code completion. This helps the IDE parse large protobuf files. ```properties # Replace the values with something less if resources are limited. # https://www.jetbrains.com/help/objc/configuring-file-size-limit.html idea.max.intellisense.filesize=60000 idea.max.content.load.filesize=60000 ``` -------------------------------- ### Run Callback Loop Source: https://github.com/longi94/javasteam/wiki/Getting-started Processes incoming callbacks in a loop, typically executed in a separate thread. ```java while (isRunning) { manager.runWaitCallbacks(1000L); } ``` -------------------------------- ### Add Bouncy Castle Cryptography Dependency Source: https://github.com/longi94/javasteam/wiki/Download Include the Bouncy Castle cryptography library, which is a required dependency for JavaSteam. Use the appropriate version for JVM or Android. ```text org.bouncycastle:bcprov-jdk18on:x.yy ``` ```text com.madgag.spongycastle:prov:1.58.0.0 ``` -------------------------------- ### QR Code Authentication with Steam Mobile App Source: https://context7.com/longi94/javasteam/llms.txt Initiates a QR code authentication session. Requires registering for URL updates and polling for the authentication result. Use this for logging in without username/password. ```java import in.dragonbra.javasteam.steam.authentication.*; import in.dragonbra.javasteam.steam.steamclient.SteamClient; import in.dragonbra.javasteam.steam.handlers.steamuser.LogOnDetails; import in.dragonbra.javasteam.steam.handlers.steamuser.SteamUser; public class QRAuthentication implements IChallengeUrlChanged { private SteamClient steamClient; private SteamUser steamUser; private void onConnected() { try { SteamAuthentication auth = new SteamAuthentication(steamClient); AuthSessionDetails authDetails = new AuthSessionDetails(); // Begin QR authentication session QrAuthSession authSession = auth.beginAuthSessionViaQR(authDetails).get(); // Register for QR code URL updates (Steam refreshes periodically) authSession.setChallengeUrlChanged(this); // Display initial QR code System.out.println("Scan this URL with Steam Mobile App:"); System.out.println(authSession.getChallengeUrl()); // Wait for user to scan and approve AuthPollResult pollResponse = authSession.pollingWaitForResult().get(); System.out.println("Authenticated as: " + pollResponse.getAccountName()); // Log on with received tokens LogOnDetails details = new LogOnDetails(); details.setUsername(pollResponse.getAccountName()); details.setAccessToken(pollResponse.getRefreshToken()); details.setLoginID(149); steamUser.logOn(details); } catch (Exception e) { System.err.println("QR Auth failed: " + e.getMessage()); } } @Override public void onChanged(QrAuthSession qrAuthSession) { // QR code URL was refreshed, display new URL System.out.println("New QR URL: " + qrAuthSession.getChallengeUrl()); } } ``` -------------------------------- ### Retrieve and Process Steam Achievements Source: https://context7.com/longi94/javasteam/llms.txt Demonstrates how to request user stats for a specific App ID and iterate through the returned achievement blocks to display status and metadata. ```java import in.dragonbra.javasteam.steam.handlers.steamuserstats.SteamUserStats; import in.dragonbra.javasteam.steam.handlers.steamuserstats.AchievementBlocks; import in.dragonbra.javasteam.steam.handlers.steamuserstats.callback.UserStatsCallback; import in.dragonbra.javasteam.types.SteamID; import in.dragonbra.javasteam.enums.EResult; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; public class AchievementsExample { private SteamClient steamClient; private SteamUserStats steamUserStats; private SteamID currentUserSteamID; private CallbackManager manager; public void setup() { steamUserStats = steamClient.getHandler(SteamUserStats.class); manager.subscribe(UserStatsCallback.class, this::onUserStats); } private void onLoggedOn(LoggedOnCallback callback) { currentUserSteamID = callback.getClientSteamID(); // Request achievements for Team Fortress 2 (App ID 440) steamUserStats.getUserStats(440, currentUserSteamID); } private void onUserStats(UserStatsCallback callback) { System.out.println("Achievement data received for Game ID: " + callback.getGameId()); if (callback.getResult() != EResult.OK) { System.err.println("Failed to get achievements: " + callback.getResult()); return; } // Get expanded individual achievements List achievements = callback.getExpandedAchievements(); System.out.println("Total Achievements: " + achievements.size()); // Count unlocked achievements long unlockedCount = achievements.stream() .filter(AchievementBlocks::isUnlocked) .count(); System.out.println("Unlocked: " + unlockedCount); System.out.println("Completion: " + String.format("%.1f%%", (unlockedCount * 100.0 / achievements.size()))); // Display each achievement SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (int i = 0; i < achievements.size(); i++) { AchievementBlocks achievement = achievements.get(i); String name = achievement.getDisplayName() != null ? achievement.getDisplayName() : "Achievement #" + achievement.getAchievementId(); System.out.println("[" + (i + 1) + "/" + achievements.size() + "] " + name); if (achievement.getDescription() != null) { System.out.println(" \"" + achievement.getDescription() + "\""); } System.out.println(" Status: " + (achievement.isUnlocked() ? "UNLOCKED" : "LOCKED")); if (achievement.isUnlocked() && achievement.getUnlockTimestamp() > 0) { String unlockDate = dateFormat.format( new Date(achievement.getUnlockTimestamp() * 1000L)); System.out.println(" Unlocked: " + unlockDate); } if (achievement.getHidden()) { System.out.println(" [Hidden Achievement]"); } } } } ``` -------------------------------- ### Register Callback Consumers Source: https://github.com/longi94/javasteam/wiki/Getting-started Registers event handlers for connection and disconnection events using the CallbackManager. ```java CallbackManager manager = new CallbackManager(steamClient); manager.subscribe(ConnectedCallback.class, this::onConnected); manager.subscribe(DisconnectedCallback.class, this::onDisconnected); ... private void onConnected(LoggedOnCallback callback) { // handle connected event here, e.g. log in } private void DisconnectedCallback(DisconnectedCallback callback) { // handle disconnected event here, e.g. reconnect } ``` -------------------------------- ### Generate Steam Web Cookies Source: https://context7.com/longi94/javasteam/llms.txt Generates a Steam web cookie (steamLoginSecure) after successful authentication. Includes logic for renewing access tokens and updating the cookie. Use this to access Steam web services. ```java import in.dragonbra.javasteam.steam.authentication.*; import in.dragonbra.javasteam.steam.handlers.steamuser.callback.LoggedOnCallback; public class WebCookieGeneration { private SteamClient steamClient; private SteamAuthentication auth; private String accessToken; private String refreshToken; private void afterAuthentication(AuthPollResult pollResponse) { // Store tokens after successful authentication accessToken = pollResponse.getAccessToken(); refreshToken = pollResponse.getRefreshToken(); } private void onLoggedOn(LoggedOnCallback callback) { // Generate the steamLoginSecure cookie String steamLoginSecure = callback.getClientSteamID().convertToUInt64() + "||" + accessToken; System.out.println("Steam Login Cookie: " + steamLoginSecure); // Use this cookie on Steam web domains (store.steampowered.com, etc.) // Access token expires in ~24 hours, renew it: try { AccessTokenGenerateResult newTokens = auth .generateAccessTokenForApp(callback.getClientSteamID(), refreshToken, false) .get(); accessToken = newTokens.getAccessToken(); // Steam may return a new refresh token if (newTokens.getRefreshToken() != null && !newTokens.getRefreshToken().isEmpty()) { refreshToken = newTokens.getRefreshToken(); } // Update your steamLoginSecure cookie with new accessToken String updatedCookie = callback.getClientSteamID().convertToUInt64() + "||" + accessToken; System.out.println("Renewed Cookie: " + updatedCookie); } catch (Exception e) { System.err.println("Token renewal failed: " + e.getMessage()); } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.