修discordRPC加载失败会崩溃
This commit is contained in:
@@ -1,93 +1,21 @@
|
||||
local appId='1288557386700951554'
|
||||
|
||||
local ffi=require"ffi"
|
||||
|
||||
|
||||
-- Get the host os to load correct lib
|
||||
local osname=love.system.getOS()
|
||||
local discordRPClib=nil
|
||||
|
||||
-- FFI requires the libraries really be files just sitting in the filesystem. It
|
||||
-- can't load libraries from a .love archive, nor a fused executable on Windows.
|
||||
-- Merely using love.filesystem.getSource() only works when running LOVE with
|
||||
-- the game unarchived from command line, like "love .".
|
||||
--
|
||||
-- The code here setting "source" will set the directory where the game was run
|
||||
-- from, so FFI can load discordRPC. We assume that the discordRPC library's
|
||||
-- libs directory is in the same directory as the .love archive; if it's
|
||||
-- missing, it just won't load.
|
||||
local source=love.filesystem.getSource()
|
||||
if string.sub(source, -5)==".love" or love.filesystem.isFused() then
|
||||
source=love.filesystem.getSourceBaseDirectory()
|
||||
local RPC_C
|
||||
if SYSTEM=='Windows' then
|
||||
local suc
|
||||
suc,RPC_C=pcall(ffi.load,"discord-rpc")
|
||||
if not (suc and RPC_C) then
|
||||
print("Failed to load Discord-RPC lib",RPC_C)
|
||||
MES.new('error',"Failed to load Discord-RPC lib")
|
||||
RPC_C=nil
|
||||
end
|
||||
end
|
||||
|
||||
if osname=="Linux" then
|
||||
discordRPClib=ffi.load(source.."/libs/discord-rpc.so")
|
||||
elseif osname=="OS X" then
|
||||
discordRPClib=ffi.load(source.."/libs/discord-rpc.dylib")
|
||||
elseif osname=="Windows" then
|
||||
-- I would strongly advise never touching this. It was not trivial to get correct. -nightmareci
|
||||
|
||||
ffi.cdef[[
|
||||
typedef uint32_t DWORD;
|
||||
typedef char CHAR;
|
||||
typedef CHAR *LPSTR;
|
||||
typedef const CHAR *LPCSTR;
|
||||
typedef wchar_t WCHAR;
|
||||
typedef WCHAR *LPWSTR;
|
||||
typedef LPWSTR PWSTR;
|
||||
typedef const WCHAR *LPCWSTR;
|
||||
|
||||
static const DWORD CP_UTF8 = 65001;
|
||||
int32_t MultiByteToWideChar(
|
||||
DWORD CodePage,
|
||||
DWORD dwFlags,
|
||||
LPCSTR lpMultiByteStr,
|
||||
int32_t cbMultiByte,
|
||||
LPWSTR lpWideCharStr,
|
||||
int32_t cchWideChar
|
||||
);
|
||||
|
||||
int32_t WideCharToMultiByte(
|
||||
DWORD CodePage,
|
||||
DWORD dwFlags,
|
||||
LPCWSTR lpWideCharStr,
|
||||
int32_t cchWideChar,
|
||||
LPSTR lpMultiByteStr,
|
||||
int32_t cbMultiByte,
|
||||
void* lpDefaultChar,
|
||||
void* lpUsedDefaultChar
|
||||
);
|
||||
|
||||
DWORD GetShortPathNameW(
|
||||
LPCWSTR lpszLongPath,
|
||||
LPWSTR lpszShortPath,
|
||||
DWORD cchBuffer
|
||||
);
|
||||
]]
|
||||
|
||||
local originalWideSize=ffi.C.MultiByteToWideChar(ffi.C.CP_UTF8, 0, source, -1, nil, 0)
|
||||
local originalWide=ffi.new('WCHAR[?]', originalWideSize)
|
||||
ffi.C.MultiByteToWideChar(ffi.C.CP_UTF8, 0, source, -1, originalWide, originalWideSize)
|
||||
|
||||
local sourceSize=ffi.C.GetShortPathNameW(originalWide, nil, 0)
|
||||
local sourceWide=ffi.new('WCHAR[?]', sourceSize)
|
||||
ffi.C.GetShortPathNameW(originalWide, sourceWide, sourceSize)
|
||||
|
||||
local sourceChar=ffi.new('char[?]', sourceSize)
|
||||
ffi.C.WideCharToMultiByte(ffi.C.CP_UTF8, 0, sourceWide, sourceSize, sourceChar, sourceSize, nil, nil)
|
||||
|
||||
discordRPClib=ffi.load("discord-rpc.dll")
|
||||
-- source = ffi.string(sourceChar)
|
||||
-- if jit.arch == "x86" then
|
||||
-- discordRPClib = ffi.load(source.."/libs/discord-rpc_x86.dll")
|
||||
-- elseif jit.arch == "x64" then
|
||||
-- discordRPClib = ffi.load(source.."/libs/discord-rpc_x64.dll")
|
||||
-- end
|
||||
else
|
||||
-- Else it crashes later on
|
||||
error(string.format("Discord rpc not supported on platform (%s)", osname))
|
||||
end
|
||||
|
||||
|
||||
local RPC
|
||||
if RPC_C then
|
||||
RPC={}
|
||||
ffi.cdef[[
|
||||
typedef struct DiscordRichPresence {
|
||||
const char* state; /* max 128 bytes */
|
||||
@@ -134,25 +62,14 @@ void Discord_Initialize(const char* applicationId,
|
||||
DiscordEventHandlers* handlers,
|
||||
int autoRegister,
|
||||
const char* optionalSteamId);
|
||||
|
||||
void Discord_Shutdown(void);
|
||||
|
||||
void Discord_RunCallbacks(void);
|
||||
|
||||
void Discord_UpdatePresence(const DiscordRichPresence* presence);
|
||||
|
||||
void Discord_ClearPresence(void);
|
||||
|
||||
void Discord_Respond(const char* userid, int reply);
|
||||
|
||||
void Discord_UpdateHandlers(DiscordEventHandlers* handlers);
|
||||
]]
|
||||
|
||||
local RPC={} -- module table
|
||||
|
||||
-- proxy to detect garbage collection of the module
|
||||
RPC.gcDummy=newproxy(true)
|
||||
|
||||
local function unpackDiscordUser(request)
|
||||
return ffi.string(request.userId),ffi.string(request.username),
|
||||
ffi.string(request.discriminator),ffi.string(request.avatar)
|
||||
@@ -241,16 +158,16 @@ function RPC.initialize(applicationId,autoRegister,optionalSteamId)
|
||||
eventHandlers.spectateGame=spectateGame_proxy
|
||||
eventHandlers.joinRequest=joinRequest_proxy
|
||||
|
||||
discordRPClib.Discord_Initialize(applicationId, eventHandlers,
|
||||
RPC_C.Discord_Initialize(applicationId,eventHandlers,
|
||||
autoRegister and 1 or 0,optionalSteamId)
|
||||
end
|
||||
|
||||
function RPC.shutdown()
|
||||
discordRPClib.Discord_Shutdown()
|
||||
RPC_C.Discord_Shutdown()
|
||||
end
|
||||
|
||||
function RPC.runCallbacks()
|
||||
discordRPClib.Discord_RunCallbacks()
|
||||
RPC_C.Discord_RunCallbacks()
|
||||
end
|
||||
-- http://luajit.org/ext_ffi_semantics.html#callback :
|
||||
-- It is not allowed, to let an FFI call into a C function (runCallbacks)
|
||||
@@ -305,11 +222,11 @@ function RPC.updatePresence(presence)
|
||||
cpresence.spectateSecret=presence.spectateSecret
|
||||
cpresence.instance=presence.instance or 0
|
||||
|
||||
discordRPClib.Discord_UpdatePresence(cpresence)
|
||||
RPC_C.Discord_UpdatePresence(cpresence)
|
||||
end
|
||||
|
||||
function RPC.clearPresence()
|
||||
discordRPClib.Discord_ClearPresence()
|
||||
RPC_C.Discord_ClearPresence()
|
||||
end
|
||||
|
||||
local replyMap={
|
||||
@@ -321,11 +238,12 @@ local replyMap={
|
||||
-- maybe let reply take ints too (0, 1, 2) and add constants to the module
|
||||
function RPC.respond(userId,reply)
|
||||
checkStrArg(userId,nil,"userId","discordRPC.respond")
|
||||
assert(replyMap[reply], "Argument 'reply' to discordRPC.respond has to be one of \"yes\", \"no\" or \"ignore\"")
|
||||
discordRPClib.Discord_Respond(userId, replyMap[reply])
|
||||
assert(replyMap[reply],"Argument 'reply' to discordRPC.respond must be 'yes'|'no'|'ignore'")
|
||||
RPC_C.Discord_Respond(userId,replyMap[reply])
|
||||
end
|
||||
|
||||
-- garbage collection callback
|
||||
RPC.gcDummy=newproxy(true)
|
||||
getmetatable(RPC.gcDummy).__gc=function()
|
||||
RPC.shutdown()
|
||||
ready_proxy:free()
|
||||
@@ -336,8 +254,30 @@ getmetatable(RPC.gcDummy).__gc=function()
|
||||
joinRequest_proxy:free()
|
||||
end
|
||||
|
||||
function RPC.ready(userId,username,discriminator,avatar)
|
||||
print(string.format("Discord: ready (%s,%s,%s,%s)",userId,username,discriminator,avatar))
|
||||
end
|
||||
function RPC.disconnected(errorCode,message)
|
||||
print(string.format("Discord: disconnected (%d: %s)",errorCode,message))
|
||||
end
|
||||
function RPC.errored(errorCode,message)
|
||||
print(string.format("Discord: error (%d: %s)",errorCode,message))
|
||||
end
|
||||
function RPC.joinGame(joinSecret)
|
||||
print(string.format("Discord: join (%s)",joinSecret))
|
||||
end
|
||||
function RPC.spectateGame(spectateSecret)
|
||||
print(string.format("Discord: spectate (%s)",spectateSecret))
|
||||
end
|
||||
function RPC.joinRequest(userId,username,discriminator,avatar)
|
||||
print(string.format("Discord: join request (%s,%s,%s,%s)",userId,username,discriminator,avatar))
|
||||
RPC.respond(userId,'yes')
|
||||
end
|
||||
RPC.initialize(appId,true)
|
||||
end
|
||||
|
||||
local MyRPC={
|
||||
appId='1288557386700951554',
|
||||
C=RPC_C,
|
||||
RPC=RPC,
|
||||
presence={
|
||||
startTimestamp=os.time(),
|
||||
@@ -349,51 +289,28 @@ local MyRPC={
|
||||
smallImageText="",
|
||||
},
|
||||
}
|
||||
if RPC then
|
||||
function RPC.ready(userId,username,discriminator,avatar)
|
||||
print(string.format("Discord: ready (%s,%s,%s,%s)",userId,username,discriminator,avatar))
|
||||
end
|
||||
|
||||
function RPC.disconnected(errorCode,message)
|
||||
print(string.format("Discord: disconnected (%d: %s)",errorCode,message))
|
||||
end
|
||||
|
||||
function RPC.errored(errorCode,message)
|
||||
print(string.format("Discord: error (%d: %s)",errorCode,message))
|
||||
end
|
||||
|
||||
function RPC.joinGame(joinSecret)
|
||||
print(string.format("Discord: join (%s)",joinSecret))
|
||||
end
|
||||
|
||||
function RPC.spectateGame(spectateSecret)
|
||||
print(string.format("Discord: spectate (%s)",spectateSecret))
|
||||
end
|
||||
|
||||
function RPC.joinRequest(userId,username,discriminator,avatar)
|
||||
print(string.format("Discord: join request (%s,%s,%s,%s)",userId,username,discriminator,avatar))
|
||||
RPC.respond(userId,'yes')
|
||||
end
|
||||
|
||||
RPC.initialize(MyRPC.appId,true)
|
||||
else
|
||||
print("DiscordRPC loading error")
|
||||
print(RPC)
|
||||
end
|
||||
|
||||
---@class DiscordRPC.presence
|
||||
---@field startTimestamp? number
|
||||
---@field details? string
|
||||
---@field state? string
|
||||
---@field details? string
|
||||
---@field startTimestamp? number
|
||||
---@field endTimestamp? number
|
||||
---@field largeImageKey? string
|
||||
---@field largeImageText? string
|
||||
---@field smallImageKey? string
|
||||
---@field smallImageText? string
|
||||
---@field partyId? string
|
||||
---@field partySize? number
|
||||
---@field partyMax? number
|
||||
---@field matchSecret? string
|
||||
---@field joinSecret? string
|
||||
---@field spectateSecret? string
|
||||
---@field instance? number
|
||||
|
||||
---@overload fun()
|
||||
---@overload fun(state: DiscordRPC.presence)
|
||||
---@param state string
|
||||
---@param details string
|
||||
---@overload fun(new: DiscordRPC.presence)
|
||||
---@overload fun()
|
||||
function MyRPC.update(state,details)
|
||||
if state then
|
||||
for k,v in next,
|
||||
|
||||
Reference in New Issue
Block a user