diff --git a/.github/build/extraLibs/Windows_x64/discord-rpc.dll b/.github/build/extraLibs/Windows_x64/discord-rpc.dll new file mode 100644 index 00000000..8493c549 Binary files /dev/null and b/.github/build/extraLibs/Windows_x64/discord-rpc.dll differ diff --git a/.github/build/extraLibs/Windows_x86/discord-rpc.dll b/.github/build/extraLibs/Windows_x86/discord-rpc.dll new file mode 100644 index 00000000..8493c549 Binary files /dev/null and b/.github/build/extraLibs/Windows_x86/discord-rpc.dll differ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 80064e6d..3f4b4530 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -495,8 +495,8 @@ jobs: icon-path: ./.github/build/windows/${{ env.BUILD_TYPE }}/icon.ico rc-path: ./.github/build/windows/${{ env.BUILD_TYPE }}/template.rc love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }} - extra-assets-x86: ./ColdClear/x86/CCloader.dll ./ColdClear/x86/cold_clear.dll - extra-assets-x64: ./ColdClear/x64/CCloader.dll ./ColdClear/x64/cold_clear.dll + extra-assets-x86: ./ColdClear/x86/CCloader.dll ./ColdClear/x86/cold_clear.dll ./.github/build/extraLibs/Windows_x64/discord-rpc.dll + extra-assets-x64: ./ColdClear/x64/CCloader.dll ./ColdClear/x64/cold_clear.dll ./.github/build/extraLibs/Windows_x86/discord-rpc.dll product-name: ${{ steps.process-app-name.outputs.product-name }} app-id: ${{ secrets.WINDOWS_APP_ID }} project-website: https://www.studio26f.org/ diff --git a/main.lua b/main.lua index c663e5cd..42c1b828 100644 --- a/main.lua +++ b/main.lua @@ -597,6 +597,10 @@ WS.switchHost('www.studio26f.org','8081','/techmino/ws/v1') HTTP.setHost("www.studio26f.org:8081") HTTP.setThreadCount(1) +-- Discord RPC +DiscordRPC=require'parts.discordRPC' +DiscordRPC.update() + table.insert(_LOADTIMELIST_,("Load Resources: %.3fs"):format(TIME()-_LOADTIME_)) for i=1,#_LOADTIMELIST_ do LOG(_LOADTIMELIST_[i]) end diff --git a/parts/discordRPC.lua b/parts/discordRPC.lua new file mode 100644 index 00000000..f71fc02b --- /dev/null +++ b/parts/discordRPC.lua @@ -0,0 +1,410 @@ +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() +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 + + +ffi.cdef[[ +typedef struct DiscordRichPresence { + const char* state; /* max 128 bytes */ + const char* details; /* max 128 bytes */ + int64_t startTimestamp; + int64_t endTimestamp; + const char* largeImageKey; /* max 32 bytes */ + const char* largeImageText; /* max 128 bytes */ + const char* smallImageKey; /* max 32 bytes */ + const char* smallImageText; /* max 128 bytes */ + const char* partyId; /* max 128 bytes */ + int partySize; + int partyMax; + const char* matchSecret; /* max 128 bytes */ + const char* joinSecret; /* max 128 bytes */ + const char* spectateSecret; /* max 128 bytes */ + int8_t instance; +} DiscordRichPresence; + +typedef struct DiscordUser { + const char* userId; + const char* username; + const char* discriminator; + const char* avatar; +} DiscordUser; + +typedef void (*readyPtr)(const DiscordUser* request); +typedef void (*disconnectedPtr)(int errorCode, const char* message); +typedef void (*erroredPtr)(int errorCode, const char* message); +typedef void (*joinGamePtr)(const char* joinSecret); +typedef void (*spectateGamePtr)(const char* spectateSecret); +typedef void (*joinRequestPtr)(const DiscordUser* request); + +typedef struct DiscordEventHandlers { + readyPtr ready; + disconnectedPtr disconnected; + erroredPtr errored; + joinGamePtr joinGame; + spectateGamePtr spectateGame; + joinRequestPtr joinRequest; +} DiscordEventHandlers; + +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) +end + +-- callback proxies +-- note: callbacks are not JIT compiled (= SLOW), try to avoid doing performance critical tasks in them +-- luajit.org/ext_ffi_semantics.html +local ready_proxy=ffi.cast("readyPtr", function(request) + if RPC.ready then + RPC.ready(unpackDiscordUser(request)) + end +end) + +local disconnected_proxy=ffi.cast("disconnectedPtr", function(errorCode,message) + if RPC.disconnected then + RPC.disconnected(errorCode, ffi.string(message)) + end +end) + +local errored_proxy=ffi.cast("erroredPtr", function(errorCode,message) + if RPC.errored then + RPC.errored(errorCode, ffi.string(message)) + end +end) + +local joinGame_proxy=ffi.cast("joinGamePtr", function(joinSecret) + if RPC.joinGame then + RPC.joinGame(ffi.string(joinSecret)) + end +end) + +local spectateGame_proxy=ffi.cast("spectateGamePtr", function(spectateSecret) + if RPC.spectateGame then + RPC.spectateGame(ffi.string(spectateSecret)) + end +end) + +local joinRequest_proxy=ffi.cast("joinRequestPtr", function(request) + if RPC.joinRequest then + RPC.joinRequest(unpackDiscordUser(request)) + end +end) + +-- helpers +local function checkArg(arg,argType,argName,func,maybeNil) + assert(type(arg)==argType or (maybeNil and arg==nil), + string.format("Argument \"%s\" to function \"%s\" has to be of type \"%s\"", + argName, func, argType)) +end + +local function checkStrArg(arg,maxLen,argName,func,maybeNil) + if maxLen then + assert(type(arg)=="string" and arg:len()<=maxLen or (maybeNil and arg==nil), + string.format("Argument \"%s\" of function \"%s\" has to be of type string with maximum length %d", + argName, func, maxLen)) + else + checkArg(arg, "string", argName, func, true) + end +end + +local function checkIntArg(arg,maxBits,argName,func,maybeNil) + maxBits=math.min(maxBits or 32, 52) -- lua number (double) can only store integers < 2^53 + local maxVal=2^(maxBits-1) -- assuming signed integers, which, for now, are the only ones in use + assert(type(arg)=="number" and math.floor(arg)==arg + and arg=-maxVal + or (maybeNil and arg==nil), + string.format("Argument \"%s\" of function \"%s\" has to be a whole number <= %d", + argName, func, maxVal)) +end + +-- function wrappers +function RPC.initialize(applicationId,autoRegister,optionalSteamId) + local func="discordRPC.Initialize" + checkStrArg(applicationId, nil, "applicationId", func) + checkArg(autoRegister, "boolean", "autoRegister", func) + if optionalSteamId~=nil then + checkStrArg(optionalSteamId, nil, "optionalSteamId", func) + end + + local eventHandlers=ffi.new("struct DiscordEventHandlers") + eventHandlers.ready=ready_proxy + eventHandlers.disconnected=disconnected_proxy + eventHandlers.errored=errored_proxy + eventHandlers.joinGame=joinGame_proxy + eventHandlers.spectateGame=spectateGame_proxy + eventHandlers.joinRequest=joinRequest_proxy + + discordRPClib.Discord_Initialize(applicationId, eventHandlers, + autoRegister and 1 or 0, optionalSteamId) +end + +function RPC.shutdown() + discordRPClib.Discord_Shutdown() +end + +function RPC.runCallbacks() + discordRPClib.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) +-- get JIT-compiled, which in turn calls a callback, calling into Lua again (e.g. discordRPC.ready). +-- Usually this attempt is caught by the interpreter first and the C function +-- is blacklisted for compilation. +-- solution: +-- "Then you'll need to manually turn off JIT-compilation with jit.off() for +-- the surrounding Lua function that invokes such a message polling function." +jit.off(RPC.runCallbacks) + +function RPC.updatePresence(presence) + local func="discordRPC.updatePresence" + checkArg(presence, "table", "presence", func) + + -- -1 for string length because of 0-termination + checkStrArg(presence.state, 127, "presence.state", func, true) + checkStrArg(presence.details, 127, "presence.details", func, true) + + checkIntArg(presence.startTimestamp, 64, "presence.startTimestamp", func, true) + checkIntArg(presence.endTimestamp, 64, "presence.endTimestamp", func, true) + + checkStrArg(presence.largeImageKey, 31, "presence.largeImageKey", func, true) + checkStrArg(presence.largeImageText, 127, "presence.largeImageText", func, true) + checkStrArg(presence.smallImageKey, 31, "presence.smallImageKey", func, true) + checkStrArg(presence.smallImageText, 127, "presence.smallImageText", func, true) + checkStrArg(presence.partyId, 127, "presence.partyId", func, true) + + checkIntArg(presence.partySize, 32, "presence.partySize", func, true) + checkIntArg(presence.partyMax, 32, "presence.partyMax", func, true) + + checkStrArg(presence.matchSecret, 127, "presence.matchSecret", func, true) + checkStrArg(presence.joinSecret, 127, "presence.joinSecret", func, true) + checkStrArg(presence.spectateSecret, 127, "presence.spectateSecret", func, true) + + checkIntArg(presence.instance, 8, "presence.instance", func, true) + + local cpresence=ffi.new("struct DiscordRichPresence") + cpresence.state=presence.state + cpresence.details=presence.details + cpresence.startTimestamp=presence.startTimestamp or 0 + cpresence.endTimestamp=presence.endTimestamp or 0 + cpresence.largeImageKey=presence.largeImageKey + cpresence.largeImageText=presence.largeImageText + cpresence.smallImageKey=presence.smallImageKey + cpresence.smallImageText=presence.smallImageText + cpresence.partyId=presence.partyId + cpresence.partySize=presence.partySize or 0 + cpresence.partyMax=presence.partyMax or 0 + cpresence.matchSecret=presence.matchSecret + cpresence.joinSecret=presence.joinSecret + cpresence.spectateSecret=presence.spectateSecret + cpresence.instance=presence.instance or 0 + + discordRPClib.Discord_UpdatePresence(cpresence) +end + +function RPC.clearPresence() + discordRPClib.Discord_ClearPresence() +end + +local replyMap={ + no=0, + yes=1, + ignore=2, +} + +-- 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]) +end + +-- garbage collection callback +getmetatable(RPC.gcDummy).__gc=function() + RPC.shutdown() + ready_proxy:free() + disconnected_proxy:free() + errored_proxy:free() + joinGame_proxy:free() + spectateGame_proxy:free() + joinRequest_proxy:free() +end + +local MyRPC={ + appId='1288557386700951554', + RPC=RPC, + presence={ + startTimestamp=os.time(), + state="Loading...", + details="", + largeImageKey='', + largeImageText="Techmino", + smallImageKey='', + 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 largeImageKey? string +---@field largeImageText? string +---@field smallImageKey? string +---@field smallImageText? string + +---@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, + type(state)=='string' + and {state=state,details=details} + or state + do + MyRPC.presence[k]=v + end + end + if RPC then RPC.updatePresence(MyRPC.presence) end +end + +return MyRPC diff --git a/parts/scenes/app_15p.lua b/parts/scenes/app_15p.lua index 2152211d..fc43c24c 100644 --- a/parts/scenes/app_15p.lua +++ b/parts/scenes/app_15p.lua @@ -29,6 +29,7 @@ function scene.enter() slide=true pathVis=true revKB=false + DiscordRPC.update("Playing 15-Puzzle") end local function moveU(x,y) diff --git a/parts/scenes/app_2048.lua b/parts/scenes/app_2048.lua index c610e7b1..b097cb9f 100644 --- a/parts/scenes/app_2048.lua +++ b/parts/scenes/app_2048.lua @@ -234,6 +234,7 @@ function scene.enter() tapControl=false startTime=0 reset() + DiscordRPC.update("Playing 2048") end function scene.mouseDown(x,y,k) diff --git a/parts/scenes/app_AtoZ.lua b/parts/scenes/app_AtoZ.lua index bc6274fe..7e493269 100644 --- a/parts/scenes/app_AtoZ.lua +++ b/parts/scenes/app_AtoZ.lua @@ -40,6 +40,7 @@ function scene.enter() startTime=0 time=0 state=0 + DiscordRPC.update("Spamming keyboard") end function scene.keyDown(key,isRep) diff --git a/parts/scenes/app_UTTT.lua b/parts/scenes/app_UTTT.lua index 8c18067a..493dfc1b 100644 --- a/parts/scenes/app_UTTT.lua +++ b/parts/scenes/app_UTTT.lua @@ -100,6 +100,7 @@ function scene.enter() restart() BGM.play('truth') BG.set('rainbow') + DiscordRPC.update("Playing Ultimate Tic-Tac-Toe") end function scene.mouseMove(x,y) diff --git a/parts/scenes/app_arithmetic.lua b/parts/scenes/app_arithmetic.lua index e6677ac0..93a5b6f6 100644 --- a/parts/scenes/app_arithmetic.lua +++ b/parts/scenes/app_arithmetic.lua @@ -360,6 +360,7 @@ function scene.enter() drawing=false numScale=1 BGM.play('truth') + DiscordRPC.update("Playing Arithmetic") end function scene.keyDown(key,isRep) diff --git a/parts/scenes/app_calc.lua b/parts/scenes/app_calc.lua index c6a52c72..eecb76c6 100644 --- a/parts/scenes/app_calc.lua +++ b/parts/scenes/app_calc.lua @@ -28,6 +28,7 @@ function scene.enter() BG.set('none') BGM.stop() reg,val,sym=false,"0",false + DiscordRPC.update("Calculating something") end function scene.leave() BGM.play() diff --git a/parts/scenes/app_cannon.lua b/parts/scenes/app_cannon.lua index 3f3cd9e0..33eed85d 100644 --- a/parts/scenes/app_cannon.lua +++ b/parts/scenes/app_cannon.lua @@ -15,6 +15,7 @@ function scene.enter() ex,ey=626,260 BG.set('matrix') BGM.play('hang out') + DiscordRPC.update("Shooting cannon balls") end function scene.keyDown(key,isRep) diff --git a/parts/scenes/app_console.lua b/parts/scenes/app_console.lua index 50baed41..23b93978 100644 --- a/parts/scenes/app_console.lua +++ b/parts/scenes/app_console.lua @@ -1034,6 +1034,7 @@ userG.the_key=first_key function scene.enter() WIDGET.focus(inputBox) BG.set('none') + DiscordRPC.update("Hacking the system") end function scene.wheelMoved(_,y) diff --git a/parts/scenes/app_cubefield.lua b/parts/scenes/app_cubefield.lua index a6a6a711..ba3b95e4 100644 --- a/parts/scenes/app_cubefield.lua +++ b/parts/scenes/app_cubefield.lua @@ -59,6 +59,7 @@ function scene.enter() gc.setLineJoin('bevel') BGM.play('push') BG.set('none') + DiscordRPC.update("Playing Cubefield") end function scene.touchDown(x) diff --git a/parts/scenes/app_dropper.lua b/parts/scenes/app_dropper.lua index c7c1246a..aa27dd19 100644 --- a/parts/scenes/app_dropper.lua +++ b/parts/scenes/app_dropper.lua @@ -38,6 +38,7 @@ function scene.enter() state='menu' BGM.play('hang out') BG.set('space') + DiscordRPC.update("Playing Dropper") end function scene.keyDown(key,isRep) diff --git a/parts/scenes/app_dtw.lua b/parts/scenes/app_dtw.lua index b4b64c60..9a797fc8 100644 --- a/parts/scenes/app_dtw.lua +++ b/parts/scenes/app_dtw.lua @@ -201,6 +201,7 @@ function scene.enter() reset() BG.set('fixColor',.26,.26,.26) BGM.play(bgm) + DiscordRPC.update("Avoiding touching white tiles") end local function touch(n) diff --git a/parts/scenes/app_link.lua b/parts/scenes/app_link.lua index 3615daec..c3dab386 100644 --- a/parts/scenes/app_link.lua +++ b/parts/scenes/app_link.lua @@ -249,6 +249,7 @@ function scene.enter() invis=false newGame() BGM.play('truth') + DiscordRPC.update("Playing Link") end function scene.keyDown(key,isRep) diff --git a/parts/scenes/app_mahjong.lua b/parts/scenes/app_mahjong.lua index 8d55b468..d064e829 100644 --- a/parts/scenes/app_mahjong.lua +++ b/parts/scenes/app_mahjong.lua @@ -109,6 +109,7 @@ function scene.enter() BG.set('fixColor',.26,.62,.26) _newGame() selected=false + DiscordRPC.update("Playing Mahjong") end function scene.mouseMove(x,y) diff --git a/parts/scenes/app_memorize.lua b/parts/scenes/app_memorize.lua index e1844c81..9af7128d 100644 --- a/parts/scenes/app_memorize.lua +++ b/parts/scenes/app_memorize.lua @@ -36,6 +36,7 @@ function scene.enter() input='' showNum='memoriZe' BGM.play('reason') + DiscordRPC.update("Playing memoriZe") end function scene.keyDown(key,isRep) diff --git a/parts/scenes/app_piano.lua b/parts/scenes/app_piano.lua index 1c78662e..4942e8a4 100644 --- a/parts/scenes/app_piano.lua +++ b/parts/scenes/app_piano.lua @@ -95,6 +95,7 @@ function scene.enter() generateVKey() _notHoldCS() _showVirtualKey(MOBILE) + DiscordRPC.update("Playing music") end function scene.leave() diff --git a/parts/scenes/app_polyforge.lua b/parts/scenes/app_polyforge.lua index 29e4baf6..86f4d7dd 100644 --- a/parts/scenes/app_polyforge.lua +++ b/parts/scenes/app_polyforge.lua @@ -40,6 +40,7 @@ function scene.enter() end BG.set('none') BGM.play('dream') + DiscordRPC.update("Playing polyforge") end function scene.keyDown(key,isRep) diff --git a/parts/scenes/app_pong.lua b/parts/scenes/app_pong.lua index 2ee64746..06c05257 100644 --- a/parts/scenes/app_pong.lua +++ b/parts/scenes/app_pong.lua @@ -35,6 +35,7 @@ function scene.enter() vy=0, y0=false, } + DiscordRPC.update("Playing Pong") end local function start() diff --git a/parts/scenes/app_reflect.lua b/parts/scenes/app_reflect.lua index 4ed1ad74..34a814c9 100644 --- a/parts/scenes/app_reflect.lua +++ b/parts/scenes/app_reflect.lua @@ -18,6 +18,7 @@ end function scene.enter() reset() BG.set('none') + DiscordRPC.update("Playing Reflect") end function scene.keyDown(key,isRep) diff --git a/parts/scenes/app_schulteG.lua b/parts/scenes/app_schulteG.lua index 7b673503..a20b3c5d 100644 --- a/parts/scenes/app_schulteG.lua +++ b/parts/scenes/app_schulteG.lua @@ -25,6 +25,7 @@ function scene.enter() mistake=0 state=0 progress=0 + DiscordRPC.update("Playing Schulte Grid") end local function newBoard() diff --git a/parts/scenes/app_spin.lua b/parts/scenes/app_spin.lua index a0a90fb8..d2937e4b 100644 --- a/parts/scenes/app_spin.lua +++ b/parts/scenes/app_spin.lua @@ -15,6 +15,10 @@ end) local scene={} +function scene.enter() + DiscordRPC.update("Playing a non-sense thing") +end + function scene.keyDown(key,isRep) if isRep then return end if key=='space' or key=='return' then diff --git a/parts/scenes/app_stopwatch.lua b/parts/scenes/app_stopwatch.lua index 54611a93..e3e67bcb 100644 --- a/parts/scenes/app_stopwatch.lua +++ b/parts/scenes/app_stopwatch.lua @@ -27,6 +27,7 @@ function scene.enter() state=0 time1=STRING.time(0) time2=STRING.time(0) + DiscordRPC.update("Timing something") end function scene.mouseDown() diff --git a/parts/scenes/app_tap.lua b/parts/scenes/app_tap.lua index 7e5ec26a..5de5badf 100644 --- a/parts/scenes/app_tap.lua +++ b/parts/scenes/app_tap.lua @@ -14,6 +14,7 @@ function scene.enter() keyTime={} for i=1,40 do keyTime[i]=-1e99 end BG.set('fixColor',.26,.26,.26) BGM.play('push') + DiscordRPC.update("Spamming keyboard") end function scene.keyDown(key,isRep) diff --git a/parts/scenes/app_ten.lua b/parts/scenes/app_ten.lua index 7388d671..ed20e954 100644 --- a/parts/scenes/app_ten.lua +++ b/parts/scenes/app_ten.lua @@ -64,6 +64,7 @@ function scene.enter() invis=false nexts=true reset() + DiscordRPC.update("Playing Get the Ten") end local function merge() diff --git a/parts/scenes/app_triple.lua b/parts/scenes/app_triple.lua index 0dc7a977..b1888d4c 100644 --- a/parts/scenes/app_triple.lua +++ b/parts/scenes/app_triple.lua @@ -267,6 +267,7 @@ local scene={} function scene.enter() player:reset() BGM.play('truth') + DiscordRPC.update("Playing Triple Town") end function scene.mouseClick(x,y) diff --git a/parts/scenes/dict.lua b/parts/scenes/dict.lua index 329bd543..13e13819 100644 --- a/parts/scenes/dict.lua +++ b/parts/scenes/dict.lua @@ -163,6 +163,7 @@ function scene.enter() if not MOBILE then WIDGET.focus(inputBox) end BG.set('rainbow') + DiscordRPC.update("Learning Zictionary") end function scene.wheelMoved(_,y) diff --git a/parts/scenes/error.lua b/parts/scenes/error.lua index 47514ef9..63a5e9cd 100644 --- a/parts/scenes/error.lua +++ b/parts/scenes/error.lua @@ -13,6 +13,7 @@ function scene.enter() if SETTING then SFX.fplay('error',SETTING.voc*.8 or 0) end + DiscordRPC.update("Struke by an error") end function scene.draw() diff --git a/parts/scenes/game.lua b/parts/scenes/game.lua index b8c31cdf..b601765b 100644 --- a/parts/scenes/game.lua +++ b/parts/scenes/game.lua @@ -222,6 +222,8 @@ function scene.enter() _updateStepButton() _updateRepButtons() _updateMenuButtons() + + DiscordRPC.update("Playing "..GAME.curMode.name) end scene.mouseDown=NULL diff --git a/parts/scenes/lang.lua b/parts/scenes/lang.lua index 287e0f26..9cf3509e 100644 --- a/parts/scenes/lang.lua +++ b/parts/scenes/lang.lua @@ -21,6 +21,9 @@ local curLang=1 local scene={} +function scene.enter() + DiscordRPC.update("Setting language") +end function scene.leave() saveSettings() end diff --git a/parts/scenes/launchpad.lua b/parts/scenes/launchpad.lua index 195cc944..6aa9c15e 100644 --- a/parts/scenes/launchpad.lua +++ b/parts/scenes/launchpad.lua @@ -168,6 +168,10 @@ local function press(x,y) end end +function scene.enter() + DiscordRPC.update("Playing Launchpad") +end + function scene.touchDown(x,y) x,y=floor((x-pad.x)/80),floor((y-pad.y)/80) if x>=0 and x<=8 and y>=0 and y<=7 then diff --git a/parts/scenes/main.lua b/parts/scenes/main.lua index b90567bc..985ca38a 100644 --- a/parts/scenes/main.lua +++ b/parts/scenes/main.lua @@ -44,6 +44,8 @@ function scene.enter() GAME.setting={} PLY.newDemoPlayer(1) PLAYERS[1]:setPosition(520,140,.8) + + DiscordRPC.update("In Main Menu") end function scene.resize() diff --git a/parts/scenes/main_simple.lua b/parts/scenes/main_simple.lua index 74aca2ea..7308fab3 100644 --- a/parts/scenes/main_simple.lua +++ b/parts/scenes/main_simple.lua @@ -5,6 +5,7 @@ local tip=GC.newText(getFont(30),"") function scene.enter() tip:set(text.getTip()) BG.set() + DiscordRPC.update("In Simple Menu") end function scene.draw() diff --git a/parts/scenes/mode.lua b/parts/scenes/mode.lua index df4c536a..6f20afef 100644 --- a/parts/scenes/mode.lua +++ b/parts/scenes/mode.lua @@ -44,6 +44,7 @@ function scene.enter() end end modUsed=usingMod() + DiscordRPC.update("Picking mode") end local function _getK() diff --git a/parts/scenes/music.lua b/parts/scenes/music.lua index 355bdb3b..3c1345ed 100644 --- a/parts/scenes/music.lua +++ b/parts/scenes/music.lua @@ -26,6 +26,7 @@ if #bgmList==0 then bgmList={"[NO BGM]"} end function scene.enter() playing=BGM.getPlaying()[1] selected=TABLE.find(bgmList,playing) or 1 + DiscordRPC.update("Elevating the soul through music") end function scene.wheelMoved(_,y) diff --git a/parts/scenes/net_galaxim.lua b/parts/scenes/net_galaxim.lua index 9cb97d1b..3900b1ab 100644 --- a/parts/scenes/net_galaxim.lua +++ b/parts/scenes/net_galaxim.lua @@ -5,6 +5,7 @@ local scene={} function scene.enter() BG.set('galaxy') BGM.play('exploration') + DiscordRPC.update("Dreaming Techmino Galaxy coming out") end function scene.draw() diff --git a/parts/scenes/net_game.lua b/parts/scenes/net_game.lua index ca6a430f..cc535345 100644 --- a/parts/scenes/net_game.lua +++ b/parts/scenes/net_game.lua @@ -72,6 +72,7 @@ function scene.enter() BG.set(GAME.prevBG) GAME.prevBG=false end + DiscordRPC.update("Playing Multiplayer") end function scene.leave() TASK.unlock('netPlaying') diff --git a/parts/scenes/net_menu.lua b/parts/scenes/net_menu.lua index 5026b6a0..29c8406e 100644 --- a/parts/scenes/net_menu.lua +++ b/parts/scenes/net_menu.lua @@ -2,6 +2,7 @@ local scene={} function scene.enter() BG.set() + DiscordRPC.update("Ready to Click \"Rooms\"") end function scene.leave() NET.ws_close() diff --git a/parts/scenes/net_newRoom.lua b/parts/scenes/net_newRoom.lua index 67d2f6a1..4e462240 100644 --- a/parts/scenes/net_newRoom.lua +++ b/parts/scenes/net_newRoom.lua @@ -53,6 +53,7 @@ end function scene.enter() sure=0 destroyPlayers() + DiscordRPC.update("Creating new room...") end function scene.leave() BGM.play() diff --git a/parts/scenes/net_rooms.lua b/parts/scenes/net_rooms.lua index 25e0a153..f96fb01e 100644 --- a/parts/scenes/net_rooms.lua +++ b/parts/scenes/net_rooms.lua @@ -74,6 +74,7 @@ local scene={} function scene.enter() BG.set() _fetchRoom() + DiscordRPC.update("Checking room list") end function scene.keyDown(key) diff --git a/parts/scenes/notice.lua b/parts/scenes/notice.lua index 5da013fb..3b869c55 100644 --- a/parts/scenes/notice.lua +++ b/parts/scenes/notice.lua @@ -15,6 +15,7 @@ function scene.enter() else scene.widgetList.texts:setTexts({"No data"}) end + DiscordRPC.update("Checking Latest News") end function scene.wheelMoved(_,y) diff --git a/parts/scenes/replays.lua b/parts/scenes/replays.lua index 3d8473b3..757414ef 100644 --- a/parts/scenes/replays.lua +++ b/parts/scenes/replays.lua @@ -77,6 +77,7 @@ function scene.enter() BG.set() listBox:setList(REPLAY) _updateButtonVisibility() + DiscordRPC.update("Finding replay") end function scene.leave() if #mods>0 then diff --git a/parts/scenes/setting_control.lua b/parts/scenes/setting_control.lua index 4f74427e..52a18d67 100644 --- a/parts/scenes/setting_control.lua +++ b/parts/scenes/setting_control.lua @@ -9,6 +9,7 @@ function scene.enter() das,arr=SETTING.das,SETTING.arr pos,dir,wait=0,1,30 BG.set('bg1') + DiscordRPC.update("Tweaking control settings") end local trigFrame=0 diff --git a/parts/scenes/setting_game.lua b/parts/scenes/setting_game.lua index 0a658782..e2024445 100644 --- a/parts/scenes/setting_game.lua +++ b/parts/scenes/setting_game.lua @@ -4,6 +4,7 @@ local scene={} function scene.enter() BG.set() + DiscordRPC.update("Tweaking Settings") end function scene.leave() saveSettings() diff --git a/parts/scenes/setting_key.lua b/parts/scenes/setting_key.lua index 22e532b1..5618af6e 100644 --- a/parts/scenes/setting_key.lua +++ b/parts/scenes/setting_key.lua @@ -102,6 +102,7 @@ function scene.enter() selected=false _freshKeyList() BG.set('none') + DiscordRPC.update("Binding keys") end function scene.leave() saveFile(KEY_MAP,'conf/key') diff --git a/parts/scenes/setting_sound.lua b/parts/scenes/setting_sound.lua index 16d96199..a51ea253 100644 --- a/parts/scenes/setting_sound.lua +++ b/parts/scenes/setting_sound.lua @@ -15,6 +15,7 @@ function scene.enter() scene.widgetList.sfxPack:reset() scene.widgetList.vocPack:reset() BG.set() + DiscordRPC.update("Tweaking Settings") end function scene.leave() saveSettings() diff --git a/parts/scenes/setting_video.lua b/parts/scenes/setting_video.lua index e916a0fc..9a18c323 100644 --- a/parts/scenes/setting_video.lua +++ b/parts/scenes/setting_video.lua @@ -2,6 +2,9 @@ local gc=love.graphics local scene={} +function scene.enter() + DiscordRPC.update("Tweaking Settings") +end function scene.leave() saveSettings() end diff --git a/parts/scenes/staff.lua b/parts/scenes/staff.lua index 9b7a51e5..b34a68f9 100644 --- a/parts/scenes/staff.lua +++ b/parts/scenes/staff.lua @@ -17,6 +17,7 @@ function scene.enter() BG.set() names={} counter=26 + DiscordRPC.update("Knowing Staffs") end function scene.mouseDown(x,y) diff --git a/parts/scenes/stat.lua b/parts/scenes/stat.lua index afab7dde..59ba04ab 100644 --- a/parts/scenes/stat.lua +++ b/parts/scenes/stat.lua @@ -37,6 +37,7 @@ function scene.enter() for i=1,11 do item[i]=text.stat[i].."\t"..item[i] end + DiscordRPC.update("Admiring Oneself") end function scene.mouseDown(x,y) diff --git a/parts/scenes/support.lua b/parts/scenes/support.lua index 654060b2..a46f5061 100644 --- a/parts/scenes/support.lua +++ b/parts/scenes/support.lua @@ -1,5 +1,9 @@ local scene={} +function scene.enter() + DiscordRPC.update("Sponsoring a Great Cause") +end + function scene.draw() -- QR Code frame GC.setLineWidth(2) diff --git a/updateLog.txt b/updateLog.txt index 7eac8b1d..280d51a4 100644 --- a/updateLog.txt +++ b/updateLog.txt @@ -5,6 +5,7 @@ 新增: 新的IRS系统和一个IRS参数设置(By Electra) 新的事件系统,允许自由定义事件和参数数量,让更多的模式创意成为可能 (By Electra & MrZ) + DiscordRPC支持 主菜单添加公告页面 尝试重启联网 修复: