mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Merge pull request #21760 from misantronic/feature/achievementshost-cli-override
Android: add achievements host override receiver
This commit is contained in:
@@ -29,6 +29,8 @@ bool NativeIsAtTopLevel();
|
||||
// before this, although it may be called at any point in time afterwards (on any thread!)
|
||||
// This functions must NOT call OpenGL. Main thread.
|
||||
void NativeInit(int argc, const char *argv[], const char *savegame_dir, const char *external_dir, const char *cache_dir);
|
||||
void NativeSetAchievementsHostOverride(std::string_view host);
|
||||
void NativeClearAchievementsHostOverride();
|
||||
|
||||
// Runs after NativeInit() at some point. May (and probably should) call OpenGL.
|
||||
// Should not initialize anything screen-size-dependent - do that in NativeResized.
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
|
||||
#include "ext/rcheevos/include/rc_client.h"
|
||||
|
||||
// Background worker threads should be spawned in NativeInit and joined
|
||||
// in NativeShutdown.
|
||||
#include <errno.h>
|
||||
@@ -191,6 +193,71 @@ static Draw::Pipeline *texColorPipeline;
|
||||
static UIContext *uiContext;
|
||||
static int g_restartGraphics;
|
||||
static bool g_windowHidden = false;
|
||||
static std::string g_achievementsHostOverride;
|
||||
static std::string g_savedAchievementsHost;
|
||||
static bool g_savedAchievementsHardcoreMode = false;
|
||||
static bool g_hasSavedAchievementsSettings = false;
|
||||
static bool g_nativeMainThreadReady = false;
|
||||
|
||||
static void ApplyAchievementsRuntimeSettings() {
|
||||
auto *client = Achievements::GetClient();
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_Config.sAchievementsHost.empty()) {
|
||||
rc_client_set_host(client, g_Config.sAchievementsHost.c_str());
|
||||
} else if (!System_GetPropertyBool(SYSPROP_SUPPORTS_HTTPS)) {
|
||||
rc_client_set_host(client, "http://retroachievements.org");
|
||||
} else {
|
||||
rc_client_set_host(client, "https://retroachievements.org");
|
||||
}
|
||||
|
||||
rc_client_set_hardcore_enabled(client, g_Config.bAchievementsHardcoreMode ? 1 : 0);
|
||||
}
|
||||
|
||||
static void ApplyAchievementsHostOverride() {
|
||||
if (g_achievementsHostOverride.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_hasSavedAchievementsSettings) {
|
||||
g_savedAchievementsHost = g_Config.sAchievementsHost;
|
||||
g_savedAchievementsHardcoreMode = g_Config.bAchievementsHardcoreMode;
|
||||
g_hasSavedAchievementsSettings = true;
|
||||
}
|
||||
|
||||
g_Config.DoNotSaveSetting(&g_Config.sAchievementsHost);
|
||||
g_Config.sAchievementsHost = g_achievementsHostOverride;
|
||||
g_Config.DoNotSaveSetting(&g_Config.bAchievementsHardcoreMode);
|
||||
g_Config.bAchievementsHardcoreMode = false;
|
||||
ApplyAchievementsRuntimeSettings();
|
||||
}
|
||||
|
||||
static void ClearAchievementsHostOverride() {
|
||||
g_achievementsHostOverride.clear();
|
||||
if (!g_hasSavedAchievementsSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_Config.DoNotSaveSetting(&g_Config.sAchievementsHost);
|
||||
g_Config.sAchievementsHost = g_savedAchievementsHost;
|
||||
g_Config.DoNotSaveSetting(&g_Config.bAchievementsHardcoreMode);
|
||||
g_Config.bAchievementsHardcoreMode = g_savedAchievementsHardcoreMode;
|
||||
g_savedAchievementsHost.clear();
|
||||
g_savedAchievementsHardcoreMode = false;
|
||||
g_hasSavedAchievementsSettings = false;
|
||||
ApplyAchievementsRuntimeSettings();
|
||||
}
|
||||
|
||||
static void RunAchievementsOverrideUpdate(std::function<void()> func) {
|
||||
if (g_nativeMainThreadReady) {
|
||||
System_RunOnMainThread(std::move(func));
|
||||
} else {
|
||||
func();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::function<void()>> g_pendingClosures;
|
||||
|
||||
AudioBackend *g_audioBackend = nullptr;
|
||||
@@ -707,6 +774,8 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
|
||||
g_DownloadManager.SetCacheDir(GetSysDirectory(DIRECTORY_APP_CACHE));
|
||||
|
||||
ApplyAchievementsHostOverride();
|
||||
|
||||
DEBUG_LOG(Log::System, "ScreenManager!");
|
||||
g_screenManager = new ScreenManager();
|
||||
if (g_Config.memStickDirectory.empty()) {
|
||||
@@ -756,6 +825,21 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
|
||||
// Must be done restarting by now.
|
||||
restarting = false;
|
||||
g_nativeMainThreadReady = true;
|
||||
}
|
||||
|
||||
void NativeSetAchievementsHostOverride(std::string_view host) {
|
||||
std::string hostCopy(host);
|
||||
RunAchievementsOverrideUpdate([host = std::move(hostCopy)] {
|
||||
g_achievementsHostOverride = host;
|
||||
ApplyAchievementsHostOverride();
|
||||
});
|
||||
}
|
||||
|
||||
void NativeClearAchievementsHostOverride() {
|
||||
RunAchievementsOverrideUpdate([] {
|
||||
ClearAchievementsHostOverride();
|
||||
});
|
||||
}
|
||||
|
||||
void CallbackPostRender(UIContext *dc, void *userdata);
|
||||
@@ -1470,6 +1554,8 @@ bool NativeIsRestarting() {
|
||||
|
||||
void NativeShutdown() {
|
||||
INFO_LOG(Log::System, "NativeShutdown begin");
|
||||
ClearAchievementsHostOverride();
|
||||
g_nativeMainThreadReady = false;
|
||||
|
||||
Achievements::Shutdown();
|
||||
|
||||
|
||||
@@ -116,6 +116,14 @@
|
||||
<activity android:name=".DocumentResultProxyActivity"
|
||||
android:theme="@style/Theme.ProxyTransparent"
|
||||
android:launchMode="standard" />
|
||||
<receiver
|
||||
android:name=".AchievementsHostOverrideReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="org.ppsspp.ppsspp.action.SET_ACHIEVEMENTS_HOST_OVERRIDE" />
|
||||
<action android:name="org.ppsspp.ppsspp.action.CLEAR_ACHIEVEMENTS_HOST_OVERRIDE" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<profileable android:shell="true" android:enabled="true" />
|
||||
</application>
|
||||
|
||||
|
||||
@@ -872,6 +872,15 @@ retry:
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_setAchievementsHostOverride(JNIEnv *env, jclass, jstring jhost) {
|
||||
std::string host = GetJavaString(env, jhost);
|
||||
NativeSetAchievementsHostOverride(host);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_clearAchievementsHostOverride(JNIEnv *, jclass) {
|
||||
NativeClearAchievementsHostOverride();
|
||||
}
|
||||
|
||||
AudioBackend *System_CreateAudioBackend() {
|
||||
// Use legacy mechanisms.
|
||||
return nullptr;
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package org.ppsspp.ppsspp;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
public class AchievementsHostOverrideReceiver extends BroadcastReceiver {
|
||||
private static final String TAG = "AchievementsHostOverride";
|
||||
public static final String ACTION_SET = "org.ppsspp.ppsspp.action.SET_ACHIEVEMENTS_HOST_OVERRIDE";
|
||||
public static final String ACTION_CLEAR = "org.ppsspp.ppsspp.action.CLEAR_ACHIEVEMENTS_HOST_OVERRIDE";
|
||||
public static final String EXTRA_HOST = "host";
|
||||
private static final String PREFS_NAME = "achievements_host_override";
|
||||
private static final String KEY_HOST = "host";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent == null || intent.getAction() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
||||
String action = intent.getAction();
|
||||
|
||||
if (ACTION_CLEAR.equals(action)) {
|
||||
clearHostOverride(prefs);
|
||||
PpssppActivity.clearAchievementsHostOverride();
|
||||
Log.i(TAG, "Cleared achievements host override");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ACTION_SET.equals(action)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String host = intent.getStringExtra(EXTRA_HOST);
|
||||
if (host != null) {
|
||||
host = host.trim();
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(host)) {
|
||||
clearHostOverride(prefs);
|
||||
PpssppActivity.clearAchievementsHostOverride();
|
||||
Log.i(TAG, "Empty host received, cleared override");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAllowedHost(host)) {
|
||||
Log.w(TAG, "Rejected non-loopback achievements host override");
|
||||
return;
|
||||
}
|
||||
|
||||
prefs.edit().putString(KEY_HOST, host).apply();
|
||||
PpssppActivity.applyAchievementsHostOverride(host);
|
||||
Log.i(TAG, "Stored achievements host override");
|
||||
}
|
||||
|
||||
public static String getAchievementsHostOverride(Context context) {
|
||||
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
||||
return prefs.getString(KEY_HOST, null);
|
||||
}
|
||||
|
||||
private static void clearHostOverride(SharedPreferences prefs) {
|
||||
prefs.edit().remove(KEY_HOST).apply();
|
||||
}
|
||||
|
||||
private static boolean isAllowedHost(String host) {
|
||||
Uri uri = Uri.parse(host);
|
||||
if (uri == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!"http".equals(uri.getScheme())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!uri.isHierarchical()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String authority = uri.getEncodedAuthority();
|
||||
if (TextUtils.isEmpty(authority) || authority.contains("@")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(uri.getEncodedPath()) && !"/".equals(uri.getEncodedPath())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(uri.getEncodedQuery()) || !TextUtils.isEmpty(uri.getEncodedFragment())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int port = uri.getPort();
|
||||
if (port < 0 || port > 65535) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String parsedHost = uri.getHost();
|
||||
if (TextUtils.isEmpty(parsedHost)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return "127.0.0.1".equals(parsedHost) || "localhost".equalsIgnoreCase(parsedHost) || "::1".equals(parsedHost);
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,8 @@ public class NativeApp {
|
||||
public static native void mouseDelta(float x, float y);
|
||||
public static native void sendMessageFromJava(String msg, String arg);
|
||||
public static native void sendRequestResult(int seqID, boolean result, String value, int iValue);
|
||||
public static native void setAchievementsHostOverride(String host);
|
||||
public static native void clearAchievementsHostOverride();
|
||||
public static native String queryConfig(String queryName);
|
||||
|
||||
public static native int getSelectedCamera();
|
||||
|
||||
@@ -172,6 +172,22 @@ public class PpssppActivity extends AppCompatActivity implements SensorEventList
|
||||
|
||||
public static boolean libraryLoaded = false;
|
||||
|
||||
public static void applyAchievementsHostOverride(String host) {
|
||||
if (!initialized || !libraryLoaded || host == null || host.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
NativeApp.setAchievementsHostOverride(host);
|
||||
}
|
||||
|
||||
public static void clearAchievementsHostOverride() {
|
||||
if (!initialized || !libraryLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
NativeApp.clearAchievementsHostOverride();
|
||||
}
|
||||
|
||||
public static void CheckABIAndLoadLibrary() {
|
||||
try {
|
||||
System.loadLibrary("ppsspp_jni");
|
||||
@@ -707,6 +723,12 @@ public class PpssppActivity extends AppCompatActivity implements SensorEventList
|
||||
setShortcutParam(shortcutParam);
|
||||
}
|
||||
|
||||
String achievementsHostOverride = AchievementsHostOverrideReceiver.getAchievementsHostOverride(this);
|
||||
if (achievementsHostOverride != null && !achievementsHostOverride.isEmpty()) {
|
||||
NativeApp.setAchievementsHostOverride(achievementsHostOverride);
|
||||
Log.i(TAG, "Found achievements host override");
|
||||
}
|
||||
|
||||
lifeCycle.onCreate();
|
||||
|
||||
mSensorManager = (SensorManager)getSystemService(Activity.SENSOR_SERVICE);
|
||||
|
||||
Reference in New Issue
Block a user