Git Product home page Git Product logo

steamworks's Introduction

steamworks

⚠️Until this issue is fixed, this package only support windows. There is a workaround though, you can generate platform specific api using https://github.com/aeb-dev/steamworks_gen

Steamworks SDK wrapper written in a darty way to be used in dart projects

Published games

Here are a list of games that have been published on Steam that utilise this package:

steamworks's People

Contributors

aeb-dev avatar chirag729 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

chirag729

steamworks's Issues

Use steamUgc.getQueryUgcResult to get data will crash

steam sdk v1.57
steamworks v0.4.0
I uploaded 2 ugc items to my game demo (reviewing, unpublish)

Query all ugc items for the game, follow the guide to do

extension SteamClientEx on SteamClient {
  Future<List<SteamUgcDetails>> getAllItems(
      {required int page}) async {
    final completer = Completer<List<SteamUgcDetails>>();
    final appId = steamUtils.getAppId();
    UgcQueryHandle query = steamUgc.createQueryAllUgcRequestPage(
      EUgcQuery.rankedByLastUpdatedDate,
      EUgcMatchingUgcType.all,
      appId,
      appId,
      page, // start from 1
    );
    steamUgc.setReturnOnlyIds(query, false);
    steamUgc.setReturnKeyValueTags(query, true); // important, return item detail properties when set it to true

    final callId = steamUgc.sendQueryUgcRequest(query);
    registerCallResult<SteamUgcQueryCompleted>(
        asyncCallId: callId,
        cb: (result, failed) {
          print('Query ugc items result ${{
            'result': result.result,
            'total': result.totalMatchingResults,
            'current': result.numResultsReturned,
          }}');
          final List<SteamUgcDetails> details = [];
          if (result.result == EResult.eResultOK) {
            for (var i = 0; i < result.numResultsReturned; i++) {
              /// use calloc
              final detail = calloc<SteamUgcDetails>();
              final result = steamUgc.getQueryUgcResult(query, i, detail);
              print('getQueryUgcResult $i $result');
              details.add(detail.ref);
            }
          }
          print('details length ${details.length}');
          if (details.isNotEmpty) {
            print('item publishedFileId:${details.first.publishedFileId}');
            print('item publishedFileId:${details.last.publishedFileId}');
          }
          completer.complete(details);
        });
    return completer.future;
  }
}

Future main() async {
  SteamClient.init();
  SteamClient steamClient = SteamClient.instance;

  SteamClient.instance.getAllItems(page:1);

  while (true) {
    steamClient.runFrame();
    await Future<void>.delayed(const Duration(seconds: 1));
  }
}

The logs are different every time to run it🤣, but the exit code allway not zero, and can not use the try...catch to catch the error.

The first item id equal 0 or other number like 140698323595664
The second item id is right

Setting breakpad minidump AppID = 2550380
SteamInternal_SetMinidumpSteamID:  Caching Steam ID:  76561197999689957 [API loaded no]
Query ugc items result {result: EResult.eResultOK, total: 2, current: 2}
getQueryUgcResult 0 true
getQueryUgcResult 1 true
details length 2
item publishedFileId:0
item publishedFileId:3018190198

Process finished with exit code -1073741819 (0xC0000005)

This time missing some log, look like crashed from steamUgc.getQueryUgcResult

Setting breakpad minidump AppID = 2550380
SteamInternal_SetMinidumpSteamID:  Caching Steam ID:  76561197999689957 [API loaded no]
Query ugc items result {result: EResult.eResultOK, total: 2, current: 2}

Process finished with exit code -1073741819 (0xC0000005)

When I want to print more item info, like that:

          if (details.isNotEmpty) {
            print(
                'item publishedFileId:${details.first.publishedFileId} ${details.first.title.toDartString()}');
            print(
                'item publishedFileId:${details.last.publishedFileId} ${details.first.title.toDartString()}');
          }

It will show red error strings.

Setting breakpad minidump AppID = 2550380
SteamInternal_SetMinidumpSteamID:  Caching Steam ID:  76561197999689957 [API loaded no]
Query ugc items result {result: EResult.eResultOK, total: 2, current: 2}

===== CRASH =====
ExceptionCode=-1073741819, ExceptionFlags=0, ExceptionAddress=00007FFF20D51AFC
version=3.0.6 (stable) (Tue Jul 11 18:49:07 2023 +0000) on "windows_x64"
pid=18512, thread=16224, isolate_group=kernel-service(0000010B1B28A870), isolate=(nil)(0000000000000000)
os=windows, arch=x64, comp=no, sim=no
isolate_instructions=10b1e3a0000, vm_instructions=7ff6e1366970
fp=10b1b228df0, sp=2e4ffe7f0, pc=7fff20d51afc
Stack dump aborted because GetAndValidateThreadStackBounds failed.

Process finished with exit code -1073740940 (0xC0000374)
Setting breakpad minidump AppID = 2550380
SteamInternal_SetMinidumpSteamID:  Caching Steam ID:  76561197999689957 [API loaded no]
Query ugc items result {result: EResult.eResultOK, total: 2, current: 2}
getQueryUgcResult 0 true
../../runtime/vm/dart_api_impl.cc: 3047: error: Dart_StringToUTF8 expects there to be a current isolate. Did you forget to call Dart_CreateIsolateGroup or Dart_EnterIsolate?
version=3.0.6 (stable) (Tue Jul 11 18:49:07 2023 +0000) on "windows_x64"
pid=19540, thread=5016, isolate_group=(nil)(0000000000000000), isolate=(nil)(0000000000000000)
os=windows, arch=x64, comp=no, sim=no
isolate_instructions=0, vm_instructions=7ff6e1366970
fp=501c6feb90, sp=501c6feb90, pc=7ff6e15748f2

===== CRASH =====
ExceptionCode=-1073741819, ExceptionFlags=0, ExceptionAddress=00007FF6E14B2508
Aborting reentrant request for stack trace.

Process finished with exit code -1073740791 (0xC0000409)

image

About the Pointer<Utf8> parameters in the steamUgc.getQueryUgcPreviewUrl and steamUgc.getQueryUgcKeyValueTag

import 'package:ffi/ffi.dart';

for(var i = 0;i< total; i++){
    final detail = calloc<SteamUgcDetails>();
    steamUgc.getQueryUgcResult(result.handle, i, detail);
    // above work fine
    final previewUrl = calloc<Utf8>();
    final getPreviewUrl = steamUgc.getQueryUgcPreviewUrl(
        result.handle,
        i,
        previewUrl,
        256,
    );
    print('previewUrl $getPreviewUrl');
}

throw

error G1DE28886: Expected type 'Utf8' to be a valid and instantiated subtype of 'NativeType'.

I'm make sure the Utf8 import from ffi-2.1.0\lib\src\utf8.dart, Same definition as steamUgc.getQueryUgcPreviewUrl.

And the steamUgc.getQueryUgcKeyValueTag has same issue.

Don't hide the SteamApi class

https://partner.steamgames.com/doc/sdk/api#SteamAPI_RestartAppIfNecessary

This is optional but highly recommended as the Steam context associated with your application (including your App ID) will not be set up if the user launches the executable directly. If this occurs then SteamAPI_Init will fail and you will be unable to use the Steamworks API.
If you choose to use this then it should be the first Steamworks function call you make, right before SteamAPI_Init.

But it's hidden, at https://github.com/aeb-dev/steamworks/blob/main/lib/steamworks.dart#L3

When I unsubscribe the ugc item, the console keeps outputting two lines

ezgif-3-5c9f9e2e79

[Dispatcher] Callback request has been made but there were no callback registered for it. CallbackId: 1280010
[Dispatcher] Callback request has been made but there were no callback registered for it. CallbackId: 1280009
extension SteamClientEx on SteamClient {
  Future subscribe(int id) async {
    final complete = Completer<EResult>();
    registerCallResult<RemoteStorageUnsubscribePublishedFileResult>(
      asyncCallId: steamUgc.subscribeItem(id),
      cb: (r, f) {
        print('subscribe $id ${r.result}');
        complete.complete(r.result);
      },
    );
    return complete.future;
  }

  Future unsubscribe(int id) async {
    final complete = Completer<EResult>();
    registerCallResult<RemoteStorageUnsubscribePublishedFileResult>(
      asyncCallId: steamUgc.unsubscribeItem(id),
      cb: (r, f) {
        print('unsubscribeItem $id ${r.result}');
        complete.complete(r.result);
      },
    );
    return complete.future;
  }
}

How to set the item ugc tags?

steamUgc.setItemTags

extension SteamClientEx on SteamClien {
    updateItem(List<String> tags){
        // create handle ... 
        final tag = calloc<SteamParamStringArray>();
        // how to set tags to tags.strings
        // tag.strings is getter
        tag.strings[0] = 'tag'.toNativeUtf8(); // will crash
        tag.numStrings = 1; // numStrings is getter too, can not set value
        final setTags= steamUgc.setItemTags(handle, tag);
    }
}

Loading dynamic library (dylib) from current directory

Hey @aeb-dev,

I'm looking at macOS versus Steam, and I have a few questions about pkg:steamworks and pkg:steamworks_gen. I thought I'd put my questions here so that others benefit. So, here goes.


I noticed that steamworks_gen generates code like this (in dl.dart):

import "dart:ffi";
import "dart:io";

DynamicLibrary dl = Platform.isWindows
    ? DynamicLibrary.open("./steam_api64.dll")
    : Platform.isLinux
        ? DynamicLibrary.open("./libsteam_api.so")
        : DynamicLibrary.open("./libsteam_api.dylib");

This loads the dynamic library from the current directory. I seem to remember you saying that this is what Steamworks DLLs expects. For that reason, we have code that moves the .dylib file from Flutter assets to the current directory at startup.

That said, on macOS, things seem to work slightly differently. For security (or, "security"...) purposes, applications are packaged in directories (giant_robot.app/), and those directories are signed and, presumably, read-only. At least once the app is notarized, which is something macOS might require at some point. The idea is that Apple runs tests and diagnostics on each notarized app after it has been cryptographically signed, and so it will flag apps that change themselves at runtime as dangerous. (But don't take my word for it, please, I'm easily confused.)

The way dynamic libraries are linked from Flutter is explained here on flutter.dev. Once you do all those steps in Xcode, you then open the library from Flutter like so:

  1. Use DynamicLibrary.open('libyourlibrary.dylib') to dynamically link to the symbols.

Note that the path is omitted. Xcode makes sure the dylib is in path (and code signed).

Is this viable for libsteam_api.dylib? Or is there really some mechanism for which Steam absolutely must be in the current working directory?

I realize that the current approach (copy from assets to current working directory) seems to work. But it will (probably?) not work once we try to package the app for macOS and especially if we want to notarize it. So I'm exploring options.


Here's some on my research on the topic, for folks who're in the same boat:

A problem about the SteamClient.instance.steamFriends.activateGameOverlayToWebPage

My code

/// widget.file.id is steam ugc item id
/// 
ListTile(
  title: Text(WindowsUI.openInSteam.tr),
  trailing: Icon(Icons.chevron_right_rounded),
  onTap: () {
    SteamClient.instance.steamFriends.activateGameOverlayToWebPage(
      'https://steamcommunity.com/sharedfiles/filedetails/?id=${widget.file.id}'
          .toNativeUtf8(),
      EActivateGameOverlayToWebPageMode.default_,
    );
  },
),

In the development environment, it successfully wake up the Steam native window and open the web page in the Steam window.
But in the production environment and the program startup from steam, when pressed this ListTile, it just display a webview overlay over the flutter window, the problem is it frozen the flutter program window, can not close, can not move the window, can not interactive anything in this window, it dead.

I record a screen video.

Video_2023-09-06_195354.mp4
  • In the production mode it can not open the web page in the Steam native window?
  • It frozen the flutter window.
  • Similar api's all have the same problem, like steamFriends.activateGameOverlay, steamFriends.ActivateGameOverlayToStore

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.