Skip to content

RimuruDev/godot-cas

 
 

Repository files navigation

⚠️ Abyss Moth fork — read this first

This is a fork of damnedpie/godot-cas, maintained by Abyss Moth (RimuruDev) for our own game projects.

Godot 3 is NOT supported here. The godot3 module was removed — this fork is Godot 4 only. If you need Godot 3 support, use the upstream repo: https://github.com/damnedpie/godot-cas

What this fork adds on top of upstream:

  • Native VPN detection: isVpnActive() (+ existing isWifiOrMobileInternetEnabled()), handy to gate/adjust ad logic on the game side.
  • Godot 3 removed — leaner, Godot 4 only.
  • rebuild_aar.command — one command to rebuild the Godot 4 AAR (Gradle 8.7, JDK 17–22) and drop it into your project's addon.
  • Tuned for the Abyss Moth ad stack (config-driven mediation/permissions/consent lives in the game project, not here).

Use at your own risk. This fork is shaped around Abyss Moth's needs and is not a general-purpose, supported release — but we do ship it in production and it works fine for us. For the canonical, broadly-tested plugin, prefer upstream.

Dev Note

Warning!

  • CAS 4.7.3 tested only for Godot 4.6.3 (Steam version)
  • Godot 3 is not supported in this fork (use upstream for Godot 3)

Godot CAS 4.7.3 (Abyss Moth fork)

CAS.AI Godot GitHub License

CAS SDK 4.7.3 Android plugin for Godot. Godot 4 only (built against the Godot 4.6.x Android library). For Godot 3 use upstream.

Official Docs

Setup

Project integration

Option 1: Manual

  1. Add plugin files (.gd, .gdap, .aar) from the godot4 folder into your project's android/plugins.

  2. Add GodotCas.gd as a singleton (autoload) to your project.

  3. Add your Google AdMob ID to android/build/AndroidManifest.xml:

    <application android:label="@string/godot_project_name_string" android:allowBackup="false" android:isGame="true" android:hasFragileUserData="false" android:requestLegacyExternalStorage="false" tools:ignore="GoogleAppIndexingWarning" android:icon="@mipmap/icon">
    		<meta-data
    			android:name="com.google.android.gms.ads.APPLICATION_ID"
    			android:value="ca-app-pub-YOUR_ADMOB_ID_HERE" />
    			<!-- Other metadata... -->
  4. Get your cas_settings[settings_id].json file from CAS dashboard and put it into android/build/res/raw folder.

  5. (Optional) Add com.google.android.gms.permission.AD_ID permission to your Android export template if you want to use AD ID (which is usually the case). You can also add android.permission.ACCESS_COARSE_LOCATION and android.permission.READ_PHONE_STATE permissions if your app has real usecases for those (this can improve monetization).

Option 2: CAS Gradle plugin

CAS AI provides a Gradle plugin to make integration easier. It injects all the required dependencies, Google AdMob Pub ID, Tenjin (optional) and Ads Identifier (optional) dependencies into your Android build automatically.

To use CAS Gradle plugin, there are some key differences from Manual integration flow that you have to ensure.

  1. Make sure that Godot CAS config file (.gdap) doesn't contain any dependencies or repositores:
[config]

name="GodotCas"
binary_type="local"
binary="GodotCas.4.6.5.release.aar"

[dependencies]

remote=[]
custom_maven_repos=[]
  1. Make sure that your android/build/AndroidManifest.xml DOES NOT contain Google AdMob Pub ID to avoid conflicts with the injection that CAS Gradle plugin will make.

Now, to include CAS Gradle plugin:

  1. Go to your android/build/build.gradle and add CAS Gradle plugin to the plugins section in the top of the file:
/ Gradle build config for Godot Engine's Android port.
plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    // CAS Gradle Plugin
    id 'com.cleveradssolutions.gradle-plugin' version "4.6.5"
	//...
	//...
}
  1. Add the repositories CAS SDK and adapters need to fetch the dependencies (actual informattion here) into the allProjects / dependencies block:
allprojects {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
        maven { url "https://plugins.gradle.org/m2/" }
        maven { url "https://central.sonatype.com/repository/maven-snapshots/"}

        // CAS AI repositories
        maven {
            name = "MintegralAdsRepo"
            url = uri("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea")
            content { includeGroup("com.mbridge.msdk.oversea") }
        }
        maven {
            name = "PangleAdsRepo"  
            url = uri("https://artifact.bytedance.com/repository/pangle")
            content { includeGroup("com.pangle.global") }
        }
        maven {
            name = "ChartboostAdsRepo"  
            url = uri("https://cboost.jfrog.io/artifactory/chartboost-ads/")
            content {
                includeGroup("com.chartboost")
                includeGroup("com.iab.omid.library")
            }
        }
        maven {
            name = "YSONetworkRepo"
            url = uri("https://ysonetwork.s3.eu-west-3.amazonaws.com/sdk/android")
            content { includeGroup("com.ysocorp") }
        }
        maven {
            name = "OguryAdsRepo"  
            url = uri("https://maven.ogury.co")
            content {
                includeGroup("co.ogury")
                includeGroup("co.ogury.module")
            }
        }
        maven {
            name = "SmaatoAdsRepo"
            url = uri("https://s3.amazonaws.com/smaato-sdk-releases/")
            content { 
                includeGroup("com.smaato.android.sdk")
                includeGroup("com.verve")
            }
        }
        maven {
            name = "VerveAdsRepo"
            url = uri("https://verve.jfrog.io/artifactory/verve-gradle-release")
            content {
                includeGroup("net.pubnative")
                includeGroup("com.verve")
            }
        }

        // Godot user plugins custom maven repos
        String[] mavenRepos = getGodotPluginsMavenRepos()
        if (mavenRepos != null && mavenRepos.size() > 0) {
            for (String repoUrl : mavenRepos) {
                maven {
                    url repoUrl
                }
            }
        }
    }
}
  1. Add the cas{} configuration block somewhere below plugins{} block. Here's an example of configuration for Optimal Ads with Tenjin and Advertising Identifier included:
// Gradle build config for Godot Engine's Android port.
plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    // CAS Gradle Plugin
    id 'com.cleveradssolutions.gradle-plugin' version "4.6.5"
}

cas {
    includeOptimalAds = true
    includeTenjinSDK = true
    useAdvertisingId = true
}

Note that you don't need to specify casId here due to it usually being your package name (e.g. "com.yourstudio.yourgame") and it is specified by Godot Android build as applicationId which CAS Gradle plugin fetches on its own.

Ad network adapters

This plugin's configuration file GodotCas.gdap contains all adapters out of the box (excluding beta and cross-promo). Usually it's not desirable because your app may be not making use of all of them and having unnecessary adapters present will increase build size. Feel free to add/remove adapters and their repositories according to your needs.

Make sure to check out this list of adapters and also this guide page from CAS official wiki.

Also check adapters-list.txt for precise dependencies and repositories for Optimal and Families presets.

Other optional dependencies

com.google.android.gms:play-services-ads-identifier dependency is required if you want to use AD ID (which is usually the case).

com.tenjin:android-sdk dependency would be necessary if you want to enable automatic revenue reporting for Tenjin. See this wiki page for more details.

Initialization

Wrapper script GodotCas.gd has initialize() method which you are supposed to edit and then call in runtime. There are some methods that tweak initialization options for the SDK, and you have to call them before initializeCAS() is executed. Each method in the wrapper is documented by a comment, so make sure to inspect it.

Initialization settings

All methods below should come before initializeCAS() if called.

# Mandatory. Sets CAS ID (usually your app package or bundle ID).
# Not setting the ID before initializeCas() will lead to plugin crash.
setCasId(id:String) -> void

# CAS built in consent manager is enabled by default, but you can disable it.
# It's still recommended to use their consent manager, so better leave it be.
setUseBuiltInConsentManager(enabled:bool) -> void

# If enabled, turns test ads mode on.
setTestAdMode(enabled:bool) -> void

# See https://docs.page/cleveradssolutions/docs/Android/Impression-Level-Data#automatic-collect-ad-revenue
# If using this, make sure you have TenjinSDK dependency in GodotCas.gdap configuration.
setTenjinKey(key:String) -> void

# See https://docs.page/cleveradssolutions/docs/Android/Additional-Meta-AudienceNetwork-steps
setFacebookLDU(enabled:bool) -> void

Testing and debugging

# Debug Mode displays debug info with log tag "CAS". Disabled by default for performance.
setDebugMode(enabled:bool) -> void

# Adds testing device ID.
# see https://docs.page/cleveradssolutions/docs/Android/Enabling-test-ads#enable-test-devices
addTestDeviceId(id:String) -> void

Working with user data consent

Official wiki page

Automatic flow

CAS SDK provides automated consent screen workflow with their own consent screen.

# Shows consent manager if it is required (e.g. based on user's geo).
showConsentManagerIfRequired() -> void

# Force-shows the consent manager.
showConsentManager() -> void

Manual flow

In case you use your own consent screen, consent status can be set via these methods:

enum CONSENT_STATUS {
	UNDEFINED = 0
	ACCEPTED = 1
	DENIED = 2
}

# Use this if using your own consent manager. See CONSENT_STATUS enum.
setConsentStatus(status:int) -> void

enum CCPA_STATUS {
	UNDEFINED = 0
	OPT_OUT_SALE = 1
	OPT_IN_SALE = 2
}

# Use this if using your own consent manager. See CCPA_STATUS enum.
setCcpaStatus(status:int) -> void

Testing consent flow

You can also test consent screen behavior to make sure everything works as intended.

# Returns possible consent flow statuses as String : int dict for lookup.
getPossibleConsentFlowStatuses() -> Dictionary

# Returns possible debug geographies as String : int dict for lookup.
getPossibleDebugGeographies() -> Dictionary

# Sets debug geography for consent manager testing.
# Will have no effect unless force testing is enabled for consent manager.
setConsentDebugGeography(geography:int) -> void

# Enabled forced testing for consent manager.
setConsentForceTesting(enabled:bool) -> void

Children-directed treatment

Official wiki page

Developers who have knowledge of specific individuals as being COPPA-applicable should make use of the API discussed below to inform CAS and all downstream consumers of this information.

enum AUDIENCE {
	UNDEFINED = 0
	CHILDRED = 1
	NOT_CHILDREN = 2
}

# Specify what audience is the user in. See AUDIENCE enum.
setTaggedAudience(audienceType:int) -> void

Ad types

This plugin supports Interstitial, Rewarded, Banner and App Open ad types. Native ad type is not currently implemented due to having extremely few use cases in games.

Every ad-type has a corresponding initialization function: initializeInterstitial(), initializeRewarded() and so on. Make sure you call such a function before calling other methods relevant to an ad type.

Interstitial

Official wiki page

# Initializes the CASInterstitial object in the plugin and creates callbacks.
initializeInterstitial() -> void

# Loads the interstitial ad.
loadInterstitial() -> void

# Returns false is ad is not loaded yet or the CASInterstitial object hasn't been initialized.
isInterstitialLoaded() -> bool

# Shows the interstitial ad.
showInterstitial() -> void

# Destroys the interstitial ad instance.
destroyInterstitial() -> void

# Sets autoloading for interstitials, disabled by default.
setAutoloadInterstitial(enabled:bool) -> void

# Sets an interval between interstitial ad shows prohibiting ads from showing during it.
setMinIntervalInterstitial(seconds:int) -> void

# Restarts the interval specified by setMinIntervalInterstitial().
restartIntervalInterstitial() -> void

Rewarded

Official wiki page

# Initializes the CASRewarded object in the plugin and creates callbacks.
initializeRewarded() -> void

# Loads the rewarded ad.
loadRewarded() -> void

# Returns false is ad is not loaded yet or the CASRewarded object hasn't been initialized.
isRewardedLoaded() -> bool

# Shows the rewarded ad.
showRewarded() -> void

# Destroys the rewarded ad instance.
destroyRewarded() -> void

# Sets autoloading for rewarded, disabled by default.
setAutoloadRewarded(enabled:bool) -> void

# Enabled by default. Sets if an interstitial ad should be displayed in case there is no-fill for rewarded.
setRewardedExtraFillInterstitial(enabled:bool) -> void

Banner

Official wiki page

# Initializes CASBannerView. See BANNER_SIZE enum.
# Also see https://docs.page/cleveradssolutions/docs/Android/Banner-Ads#create-ad-view
initializeBanner(bannerSize:int) -> void

# Initializes CASBannerView with adaptive size.
# See https://docs.page/cleveradssolutions/docs/Android/Banner-Ads#get-the-ad-size
initializeAdaptiveBanner(maxWidthDpi:int) -> void

# Loads the banner ad.
loadBanner() -> void

# Returns false if ad is not loaded yet or the CASBannerView object hasn't been initialized.
isBannerLoaded() -> bool

# Sets banner visibility.
setBannerVisible(isVisible:bool) -> void

# Destroys the banner ad instance.
destroyBanner() -> void

# Sets autoloading for banner. Enabled by default.
setAutoloadBanner(enabled:bool) -> void

# Sets banner refresh interval. Should be longer than 10 seconds, 30 considered optimal (default).
setBannerRefreshInterval(seconds:int) -> void

# Disables ad refresh for banner.
disableBannerAdRefresh() -> void

# Sets banner position in device's actual viewport.
setBannerPosition(posX:float, posY:float) -> void

# Returns banner width in device's actual viewport.
getBannerWidth() -> int

# Returns banner height in device's actual viewport.
getBannerHeight() -> int

App Open ads

Official wiki page

# Initializes the CASAppOpen object in the plugin and creates callbacks.
initializeAppOpenAd() -> void

# Loads the AppOpen ad.
loadAppOpenAd() -> void

# Returns false if ad is not loaded yet or the CASAppOpen object hasn't been initialized.
isAppOpenAdLoaded() -> bool

# Shows the AppOpen ad.
showAppOpenAd() -> void

# Destroys the AppOpen ad instance.
destroyAppOpenAd() -> void

# Sets autoloading for AppOpen ad, disabled by default.
setAutoloadAppOpenAd(enabled:bool) -> void

# Sets autoshowing for AppOpen ad, disabled by default.
setAutoshowAppOpenAd(enabled:bool) -> void

IAP logging with Tenjin

You can log in-app purchase events to Tenjin with this plugin. Just make sure to obtain the necessary purchase data from Godot Google Play Billing Library Plugin.

You will probably be calling this from inside purchases_updated signal of Billing Plugin, but I strongly advise you call logging with some delay (like 2 seconds). Reason being, TenjinSDK might be suspended in this particular moment and there's a possibility that your logging attempt won't go through.

Make sure that Tenjin dependency is present in plugins GDAP file.

More info on data required can be found in Tenjin docs

# Data for arguments is supposed to be obtained from Google Billing Library plugin for Godot.
# CAS should be initialized with Tenjin key for this to work (might cause crash otherwise).
logTenjinPurchaseEvent(sku:String, currencyCode:String, quantity:int, price:float, originalJson:String, signature:String) -> void

Targeting options

Official wiki page

# See https://docs.page/cleveradssolutions/docs/Android/Targeting-options#user-id
setUserID(userID:String) -> void

# See https://docs.page/cleveradssolutions/docs/Android/Targeting-options#user-age
setUserAge(age:int) -> void

enum GENDER {
	UNKNOWN = 0,
	MALE = 1,
	FEMALE = 2
}

# See GENDER enum for the argument.
# See https://docs.page/cleveradssolutions/docs/Android/Targeting-options#user-gender
setUserGender(gender:int) -> void

# See https://docs.page/cleveradssolutions/docs/Android/Targeting-options#user-location-auto-collection
setUserLocationAutocollection(enabled:bool) -> void

# See https://docs.page/cleveradssolutions/docs/Android/Targeting-options#app-keywords
setUserAppKeywords(keywords:PoolStringArray) -> void

# See https://docs.page/cleveradssolutions/docs/Android/Targeting-options#app-content-url
setAppContentUrl(contentUrl:String) -> void

Utilities

CAS SDK can output integration status to logcat, displaying what adapters are integrated or not.

# Call Integration Helper and check current integration in logcat. LOG TAG: CASIntegrationHelper
validateIntegration() -> void

You can check if user has WIFI/Mobile traffic enabled on their device. This DOES NOT guarantee a working internet connection and only checks the status of WIFI and mobile traffic enabled in Android. For example, if user is connected to a WIFI but this WIFI doesn't give access to Internet, this will still return true.

# Returns true if the device has WIFI or Mobile traffic enabled. This doesn't guarantee real internet connection.
isWifiOrMobileInternetEnabled() -> bool

About

Godot CAS.AI Clever Ad Solution for Godot | Unofficial CAS SDK plugin for Godot 3 and Godot 4

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Java 60.3%
  • GDScript 34.3%
  • Shell 5.4%