添加discordRPC支持

This commit is contained in:
MrZ_26
2024-09-26 02:29:24 +08:00
parent a74e9033b3
commit 423d502aa4
54 changed files with 480 additions and 2 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -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/

View File

@@ -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

410
parts/discordRPC.lua Normal file
View File

@@ -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 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

View File

@@ -29,6 +29,7 @@ function scene.enter()
slide=true
pathVis=true
revKB=false
DiscordRPC.update("Playing 15-Puzzle")
end
local function moveU(x,y)

View File

@@ -234,6 +234,7 @@ function scene.enter()
tapControl=false
startTime=0
reset()
DiscordRPC.update("Playing 2048")
end
function scene.mouseDown(x,y,k)

View File

@@ -40,6 +40,7 @@ function scene.enter()
startTime=0
time=0
state=0
DiscordRPC.update("Spamming keyboard")
end
function scene.keyDown(key,isRep)

View File

@@ -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)

View File

@@ -360,6 +360,7 @@ function scene.enter()
drawing=false
numScale=1
BGM.play('truth')
DiscordRPC.update("Playing Arithmetic")
end
function scene.keyDown(key,isRep)

View File

@@ -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()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -249,6 +249,7 @@ function scene.enter()
invis=false
newGame()
BGM.play('truth')
DiscordRPC.update("Playing Link")
end
function scene.keyDown(key,isRep)

View File

@@ -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)

View File

@@ -36,6 +36,7 @@ function scene.enter()
input=''
showNum='memoriZe'
BGM.play('reason')
DiscordRPC.update("Playing memoriZe")
end
function scene.keyDown(key,isRep)

View File

@@ -95,6 +95,7 @@ function scene.enter()
generateVKey()
_notHoldCS()
_showVirtualKey(MOBILE)
DiscordRPC.update("Playing music")
end
function scene.leave()

View File

@@ -40,6 +40,7 @@ function scene.enter()
end
BG.set('none')
BGM.play('dream')
DiscordRPC.update("Playing polyforge")
end
function scene.keyDown(key,isRep)

View File

@@ -35,6 +35,7 @@ function scene.enter()
vy=0,
y0=false,
}
DiscordRPC.update("Playing Pong")
end
local function start()

View File

@@ -18,6 +18,7 @@ end
function scene.enter()
reset()
BG.set('none')
DiscordRPC.update("Playing Reflect")
end
function scene.keyDown(key,isRep)

View File

@@ -25,6 +25,7 @@ function scene.enter()
mistake=0
state=0
progress=0
DiscordRPC.update("Playing Schulte Grid")
end
local function newBoard()

View File

@@ -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

View File

@@ -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()

View File

@@ -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)

View File

@@ -64,6 +64,7 @@ function scene.enter()
invis=false
nexts=true
reset()
DiscordRPC.update("Playing Get the Ten")
end
local function merge()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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()

View File

@@ -222,6 +222,8 @@ function scene.enter()
_updateStepButton()
_updateRepButtons()
_updateMenuButtons()
DiscordRPC.update("Playing "..GAME.curMode.name)
end
scene.mouseDown=NULL

View File

@@ -21,6 +21,9 @@ local curLang=1
local scene={}
function scene.enter()
DiscordRPC.update("Setting language")
end
function scene.leave()
saveSettings()
end

View File

@@ -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

View File

@@ -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()

View File

@@ -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()

View File

@@ -44,6 +44,7 @@ function scene.enter()
end
end
modUsed=usingMod()
DiscordRPC.update("Picking mode")
end
local function _getK()

View File

@@ -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)

View File

@@ -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()

View File

@@ -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')

View File

@@ -2,6 +2,7 @@ local scene={}
function scene.enter()
BG.set()
DiscordRPC.update("Ready to Click \"Rooms\"")
end
function scene.leave()
NET.ws_close()

View File

@@ -53,6 +53,7 @@ end
function scene.enter()
sure=0
destroyPlayers()
DiscordRPC.update("Creating new room...")
end
function scene.leave()
BGM.play()

View File

@@ -74,6 +74,7 @@ local scene={}
function scene.enter()
BG.set()
_fetchRoom()
DiscordRPC.update("Checking room list")
end
function scene.keyDown(key)

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -4,6 +4,7 @@ local scene={}
function scene.enter()
BG.set()
DiscordRPC.update("Tweaking Settings")
end
function scene.leave()
saveSettings()

View File

@@ -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')

View File

@@ -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()

View File

@@ -2,6 +2,9 @@ local gc=love.graphics
local scene={}
function scene.enter()
DiscordRPC.update("Tweaking Settings")
end
function scene.leave()
saveSettings()
end

View File

@@ -17,6 +17,7 @@ function scene.enter()
BG.set()
names={}
counter=26
DiscordRPC.update("Knowing Staffs")
end
function scene.mouseDown(x,y)

View File

@@ -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)

View File

@@ -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)

View File

@@ -5,6 +5,7 @@
新增:
新的IRS系统和一个IRS参数设置(By Electra)
新的事件系统,允许自由定义事件和参数数量,让更多的模式创意成为可能 (By Electra & MrZ)
DiscordRPC支持
主菜单添加公告页面
尝试重启联网
修复: