From 90c428cf444dca65f37c01d42f6b5e4c03764599 Mon Sep 17 00:00:00 2001 From: Imple Lee <80144331+ImpleLee@users.noreply.github.com> Date: Fri, 20 Oct 2023 01:42:04 +0800 Subject: [PATCH] Save custom mode (#1007) * first step to save custom game * localize various settings in custom game * rename fields to lower cases * fix many bugs * fixes #1014 --- main.lua | 24 ---- parts/data.lua | 105 ++++++++-------- parts/eventsets/checkClearBoard.lua | 2 +- parts/gameFuncs.lua | 9 +- parts/modes/custom_clear.lua | 16 ++- parts/modes/custom_puzzle.lua | 14 +++ parts/scenes/customGame.lua | 183 ++++++++++++++++++++-------- parts/scenes/custom_field.lua | 10 +- parts/scenes/custom_mission.lua | 11 +- parts/scenes/custom_sequence.lua | 11 +- parts/scenes/net_newRoom.lua | 2 +- parts/scenes/pause.lua | 8 +- parts/scenes/replays.lua | 3 + 13 files changed, 240 insertions(+), 158 deletions(-) diff --git a/main.lua b/main.lua index 900b18b9..965bcfb7 100644 --- a/main.lua +++ b/main.lua @@ -376,30 +376,6 @@ then MES.new('error',"An error occured during loading, and some data was lost.") end --- Initialize fields, sequence, missions, gameEnv for cutsom game -local fieldData=loadFile('conf/customBoards','-string -canSkip') -if fieldData then - fieldData=STRING.split(fieldData,"!") - for i=1,#fieldData do - DATA.pasteBoard(fieldData[i],i) - end -else - FIELD[1]=DATA.newBoard() -end -local sequenceData=loadFile('conf/customSequence','-string -canSkip') -if sequenceData then - DATA.pasteSequence(sequenceData) -end -local missionData=loadFile('conf/customMissions','-string -canSkip') -if missionData then - DATA.pasteMission(missionData) -end -local customData=loadFile('conf/customEnv','-canSkip') -if customData and customData['version']==VERSION.code then - TABLE.complete(customData,CUSTOMENV) -end -TABLE.complete(require"parts.customEnv0",CUSTOMENV) - -- Update data do if type(STAT.version)~='number' then diff --git a/parts/data.lua b/parts/data.lua index d3163b97..f9e47895 100644 --- a/parts/data.lua +++ b/parts/data.lua @@ -2,7 +2,7 @@ local floor=math.floor local char,byte=string.char,string.byte local ins=table.insert -local BAG,FIELD,MISSION,CUSTOMENV,GAME=BAG,FIELD,MISSION,CUSTOMENV,GAME +local GAME=GAME local DATA={} -- Sep symbol: 33 (!) @@ -13,13 +13,13 @@ local DATA={} Encode: A[B] sequence, A = block ID, B = repeat times, no B means do not repeat. Example: "abcdefg" is [SZJLTOI], "a^aDb)" is [Z*63,Z*37,S*10] ]] -function DATA.copySequence() +function DATA.copySequence(bag) local str="" local count=1 - for i=1,#BAG+1 do - if BAG[i+1]~=BAG[i] or count==64 then - str=str..char(96+BAG[i]) + for i=1,#bag+1 do + if bag[i+1]~=bag[i] or count==64 then + str=str..char(96+bag[i]) if count>1 then str=str..char(32+count) count=1 @@ -32,7 +32,7 @@ function DATA.copySequence() return str end function DATA.pasteSequence(str) - TABLE.cut(BAG) + local bag={} local b,reg for i=1,#str do b=byte(str,i) @@ -44,20 +44,20 @@ function DATA.pasteSequence(str) end else if b>=97 and b<=125 then - ins(BAG,reg) + ins(bag,reg) reg=b-96 elseif b>=34 and b<=96 then for _=1,b-32 do - ins(BAG,reg) + ins(bag,reg) end reg=false end end end if reg then - ins(BAG,reg) + ins(bag,reg) end - return true + return true,bag end local fieldMeta={__index=function(self,h) @@ -69,8 +69,7 @@ end} function DATA.newBoard(f)-- Generate a new board return setmetatable(f and TABLE.shift(f) or{},fieldMeta) end -function DATA.copyBoard(page)-- Copy the [page] board - local F=FIELD[page or 1] +function DATA.copyBoard(F)-- Copy the [page] board local str="" -- Encode field @@ -84,21 +83,15 @@ function DATA.copyBoard(page)-- Copy the [page] board end return STRING.packBin(str) end -function DATA.copyBoards() +function DATA.copyBoards(field) local out={} - for i=1,#FIELD do - out[i]=DATA.copyBoard(i) + for i=1,#field do + out[i]=DATA.copyBoard(field[i]) end return table.concat(out,"!") end -function DATA.pasteBoard(str,page)-- Paste [str] data to [page] board - if not page then - page=1 - end - if not FIELD[page] then - FIELD[page]=DATA.newBoard() - end - local F=FIELD[page] +function DATA.pasteBoard(str)-- Paste [str] data to [page] board + local F=DATA.newBoard() -- Decode str=STRING.unpackBin(str) @@ -133,7 +126,7 @@ function DATA.pasteBoard(str,page)-- Paste [str] data to [page] board p=p+1 end - return true + return true, F end --[[ @@ -152,14 +145,14 @@ end O1=61,O2=62,O3=63,O4=64, I1=71,I2=72,I3=73,I4=74, ]] -function DATA.copyMission() +function DATA.copyMission(mission) local _ local str="" local count=1 - for i=1,#MISSION+1 do - if MISSION[i+1]~=MISSION[i] or count==13 then - _=33+MISSION[i] + for i=1,#mission+1 do + if mission[i+1]~=mission[i] or count==13 then + _=33+mission[i] str=str..char(_) if count>1 then str=str..char(113+count) @@ -174,7 +167,7 @@ function DATA.copyMission() end function DATA.pasteMission(str) local b - TABLE.cut(MISSION) + local mission={} local reg for i=1,#str do b=byte(str,i) @@ -187,28 +180,28 @@ function DATA.pasteMission(str) else if b>=34 and b<=114 then if ENUM_MISSION[reg] then - ins(MISSION,reg) + ins(mission,reg) reg=b-33 else - TABLE.cut(MISSION) + TABLE.cut(mission) return end elseif b>=115 and b<=126 then for _=1,b-113 do - ins(MISSION,reg) + ins(mission,reg) end reg=false end end end if reg then - ins(MISSION,reg) + ins(mission,reg) end - return true + return true,mission end -function DATA.copyQuestArgs() - local ENV=CUSTOMENV +function DATA.copyQuestArgs(custom_env) + local ENV=custom_env local str="".. ENV.holdCount.. (ENV.ospin and "O" or "Z").. @@ -218,12 +211,12 @@ function DATA.copyQuestArgs() end function DATA.pasteQuestArgs(str) if #str<4 then return end - local ENV=CUSTOMENV + local ENV={} ENV.holdCount= str:byte(1)-48 ENV.ospin= str:byte(2)~=90 ENV.missionKill=str:byte(3)~=90 ENV.sequence= str:sub(4) - return true + return true,ENV end local function _encode(t) @@ -309,7 +302,6 @@ function DATA.pumpRecording(str,L) end end do-- function DATA.saveReplay() - local noRecList={"custom","solo","round","techmino"} local function _getModList() local res={} for number,sel in next,GAME.mod do @@ -321,28 +313,30 @@ do-- function DATA.saveReplay() end function DATA.saveReplay() -- Filtering modes that cannot be saved - for _,v in next,noRecList do - if GAME.curModeName:find(v) then - MES.new('error',"Cannot save recording of this mode now!") - return - end + if GAME.initPlayerCount~=1 then + MES.new('error',"Cannot save recording of more than 1 player now!") + return end -- Write file local fileName=os.date("replay/%Y_%m_%d_%H%M%S.rep") if not love.filesystem.getInfo(fileName) then + local metadata={ + date=os.date("%Y/%m/%d %H:%M:%S"), + mode=GAME.curModeName, + version=VERSION.string, + player=USERS.getUsername(USER.uid), + seed=GAME.seed, + setting=GAME.setting, + mod=_getModList(), + tasUsed=GAME.tasUsed, + } + if GAME.curMode.savePrivate then + metadata.private=GAME.curMode.savePrivate() + end love.filesystem.write(fileName, love.data.compress('string','zlib', - JSON.encode{ - date=os.date("%Y/%m/%d %H:%M:%S"), - mode=GAME.curModeName, - version=VERSION.string, - player=USERS.getUsername(USER.uid), - seed=GAME.seed, - setting=GAME.setting, - mod=_getModList(), - tasUsed=GAME.tasUsed, - }.."\n".. + JSON.encode(metadata).."\n".. DATA.dumpRecording(GAME.rep) ) ) @@ -397,6 +391,9 @@ function DATA.parseReplayData(fileName,fileData,ifFull) tasUsed=metaData.tasUsed, } if ifFull then rep.data=fileData end + if metaData.private then + rep.private=metaData.private + end return rep end return DATA diff --git a/parts/eventsets/checkClearBoard.lua b/parts/eventsets/checkClearBoard.lua index a6016c77..40e87d48 100644 --- a/parts/eventsets/checkClearBoard.lua +++ b/parts/eventsets/checkClearBoard.lua @@ -8,7 +8,7 @@ return { for i=#P.field,1,-1 do P.field[i],P.visTime[i]=nil end - setField(P,D.finished+1) + setField(P,FIELD[D.finished+1]) SYSFX.newShade(1.4,P.absFieldX,P.absFieldY,300*P.size,610*P.size,.6,.8,.6) SFX.play('warn_1') else diff --git a/parts/gameFuncs.lua b/parts/gameFuncs.lua index 66ae7557..3b4b337b 100644 --- a/parts/gameFuncs.lua +++ b/parts/gameFuncs.lua @@ -424,8 +424,7 @@ function notEmptyLine(L) end end end -function setField(P,page) - local F=FIELD[page] +function setField(P,F) local height=0 for y=#F,1,-1 do if notEmptyLine(F[y]) then @@ -1228,8 +1227,7 @@ do-- function pressKey(k) return cache[k] end end -do-- CUS/SETXXX(k) - local CUSTOMENV=CUSTOMENV +do-- SETXXX(k) local warnList={ 'das','arr','dascut','dropcut','sddas','sdarr', 'ihs','irs','ims','RS', @@ -1237,13 +1235,10 @@ do-- CUS/SETXXX(k) 'VKSwitch','VKIcon','VKTrack','VKDodge', 'simpMode', } - function CUSval(k) return function() return CUSTOMENV[k] end end function ROOMval(k) return function() return ROOMENV[k] end end function SETval(k) return function() return SETTING[k] end end - function CUSrev(k) return function() CUSTOMENV[k]=not CUSTOMENV[k] end end function ROOMrev(k) return function() ROOMENV[k]=not ROOMENV[k] end end function SETrev(k) return function() if TABLE.find(warnList,k) then trySettingWarn() end SETTING[k]=not SETTING[k] end end - function CUSsto(k) return function(i) CUSTOMENV[k]=i end end function ROOMsto(k) return function(i) ROOMENV[k]=i end end function SETsto(k) return function(i) if TABLE.find(warnList,k) then trySettingWarn() end SETTING[k]=i end end end diff --git a/parts/modes/custom_clear.lua b/parts/modes/custom_clear.lua index 1146f243..06ac187a 100644 --- a/parts/modes/custom_clear.lua +++ b/parts/modes/custom_clear.lua @@ -19,7 +19,21 @@ return { end for _,P in next,PLY_ALIVE do - setField(P,1) + setField(P,FIELD[1]) end end, + savePrivate=function() + return { + FIELD=FIELD, + BAG=BAG, + MISSION=MISSION, + CUSTOMENV=CUSTOMENV, + } + end, + loadPrivate=function(private) + FIELD=private.FIELD + BAG=private.BAG + MISSION=private.MISSION + CUSTOMENV=private.CUSTOMENV + end, } diff --git a/parts/modes/custom_puzzle.lua b/parts/modes/custom_puzzle.lua index 9abc7362..efb43f32 100644 --- a/parts/modes/custom_puzzle.lua +++ b/parts/modes/custom_puzzle.lua @@ -60,4 +60,18 @@ return { PLY.newAIPlayer(2,BOT.template{type='CC',speedLV=2*AIlevel-1,next=math.floor(AIlevel*.5+1),hold=GAME.modeEnv.holdCount,node=20000+5000*AIlevel}) end end, + savePrivate=function() + return { + FIELD=FIELD, + BAG=BAG, + MISSION=MISSION, + CUSTOMENV=CUSTOMENV, + } + end, + loadPrivate=function(private) + FIELD=private.FIELD + BAG=private.BAG + MISSION=private.MISSION + CUSTOMENV=private.CUSTOMENV + end, } diff --git a/parts/scenes/customGame.lua b/parts/scenes/customGame.lua index 043eb995..03eab887 100644 --- a/parts/scenes/customGame.lua +++ b/parts/scenes/customGame.lua @@ -1,6 +1,63 @@ local gc,kb,sys=love.graphics,love.keyboard,love.system local floor=math.floor -local CUSTOMENV=CUSTOMENV + +CUSTOMGAME_LOCAL={ + field={}, + bag={}, + mission={}, + customenv={}, + CUSval=function(self,k) return function() return self.customenv[k] end end, + CUSrev=function(self,k) return function() self.customenv[k]=not self.customenv[k] end end, + CUSsto=function(self,k) return function(i) self.customenv[k]=i end end, +} +local function CUSval(k) return CUSTOMGAME_LOCAL:CUSval(k) end +local function CUSrev(k) return CUSTOMGAME_LOCAL:CUSrev(k) end +local function CUSsto(k) return CUSTOMGAME_LOCAL:CUSsto(k) end +local function apply_locals() + FIELD=CUSTOMGAME_LOCAL.field + BAG=CUSTOMGAME_LOCAL.bag + MISSION=CUSTOMGAME_LOCAL.mission + CUSTOMENV=CUSTOMGAME_LOCAL.customenv +end +do -- Initialize fields, sequence, missions, gameEnv for cutsom game + local fieldData=loadFile('conf/customBoards','-string -canSkip') + local fieldReinit=false + if not fieldData then + fieldReinit=true + else + fieldData=STRING.split(fieldData,"!") + for i=1,#fieldData do + local success,F=DATA.pasteBoard(fieldData[i]) + if not success then + fieldReinit=true + break + end + CUSTOMGAME_LOCAL.field[i]=F + end + end + if fieldReinit then + CUSTOMGAME_LOCAL.field={DATA.newBoard()} + end + local sequenceData=loadFile('conf/customSequence','-string -canSkip') + if sequenceData then + local success,bag=DATA.pasteSequence(sequenceData) + if success then + CUSTOMGAME_LOCAL.bag=bag + end + end + local missionData=loadFile('conf/customMissions','-string -canSkip') + if missionData then + local success,mission=DATA.pasteMission(missionData) + if success then + CUSTOMGAME_LOCAL.mission=mission + end + end + local customData=loadFile('conf/customEnv','-canSkip') + if customData and customData['version']==VERSION.code then + TABLE.complete(customData,CUSTOMGAME_LOCAL.customenv) + end + TABLE.complete(require"parts.customEnv0",CUSTOMGAME_LOCAL.customenv) +end local sList={ visible={"show","easy","slow","medium","fast","none"}, @@ -27,96 +84,114 @@ local scene={} function scene.enter() destroyPlayers() - BG.set(CUSTOMENV.bg) - BGM.play(CUSTOMENV.bgm) + BG.set(CUSTOMGAME_LOCAL.customenv.bg) + BGM.play(CUSTOMGAME_LOCAL.customenv.bgm) modUsed=usingMod() end function scene.leave() - saveFile(CUSTOMENV,'conf/customEnv') + saveFile(CUSTOMGAME_LOCAL.customenv,'conf/customEnv') BGM.play() end local function _play(mode) - if CUSTOMENV.opponent~="X" then - if CUSTOMENV.opponent:sub(1,2)=='CC' then - if CUSTOMENV.sequence=='fixed' then + if CUSTOMGAME_LOCAL.customenv.opponent~="X" then + if CUSTOMGAME_LOCAL.customenv.opponent:sub(1,2)=='CC' then + if CUSTOMGAME_LOCAL.customenv.sequence=='fixed' then MES.new('error',text.cc_fixed) return end - if CUSTOMENV.holdMode=='swap' then + if CUSTOMGAME_LOCAL.customenv.holdMode=='swap' then MES.new('error',text.cc_swap) return end end - if #BAG>0 then - for _=1,#BAG do - if BAG[_]>7 then + if #CUSTOMGAME_LOCAL.bag>0 then + for _=1,#CUSTOMGAME_LOCAL.bag do + if CUSTOMGAME_LOCAL.bag[_]>7 then MES.new('error',text.ai_prebag) return end end end - if #MISSION>0 then + if #CUSTOMGAME_LOCAL.mission>0 then MES.new('error',text.ai_mission) return end end - saveFile(CUSTOMENV,'conf/customEnv') + saveFile(CUSTOMGAME_LOCAL.customenv,'conf/customEnv') + apply_locals() loadGame('custom_'..mode,true) end function scene.keyDown(key,isRep) if isRep then return true end if key=='return' and kb.isDown('lctrl','lalt') or key=='play1' or key=='play2' then - if (key=='play2' or kb.isDown('lalt')) and #FIELD[1]>0 then + if (key=='play2' or kb.isDown('lalt')) and #CUSTOMGAME_LOCAL.field[1]>0 then _play('puzzle') elseif key=='play1' or kb.isDown('lctrl') then _play('clear') end elseif key=='f' then + apply_locals() SCN.go('custom_field','swipeD') elseif key=='s' then + apply_locals() SCN.go('custom_sequence','swipeD') elseif key=='m' then + apply_locals() SCN.go('custom_mission','swipeD') elseif key=='delete' then if tryReset() then - TABLE.cut(FIELD)TABLE.cut(BAG)TABLE.cut(MISSION) - FIELD[1]=DATA.newBoard() - TABLE.clear(CUSTOMENV) - TABLE.complete(require"parts.customEnv0",CUSTOMENV) + TABLE.cut(CUSTOMGAME_LOCAL.field)TABLE.cut(CUSTOMGAME_LOCAL.bag)TABLE.cut(CUSTOMGAME_LOCAL.mission) + CUSTOMGAME_LOCAL.field[1]=DATA.newBoard() + TABLE.clear(CUSTOMGAME_LOCAL.customenv) + TABLE.complete(require"parts.customEnv0",CUSTOMGAME_LOCAL.customenv) for _,W in next,scene.widgetList do W:reset() end - saveFile(DATA.copyMission(),'conf/customMissions') - saveFile(DATA.copyBoards(),'conf/customBoards') - saveFile(DATA.copySequence(),'conf/customSequence') - saveFile(CUSTOMENV,'conf/customEnv') + saveFile(DATA.copyMission(CUSTOMGAME_LOCAL.mission),'conf/customMissions') + saveFile(DATA.copyBoards(CUSTOMGAME_LOCAL.field),'conf/customBoards') + saveFile(DATA.copySequence(CUSTOMGAME_LOCAL.bag),'conf/customSequence') + saveFile(CUSTOMGAME_LOCAL.customenv,'conf/customEnv') SFX.play('finesseError',.7) - BG.set(CUSTOMENV.bg) - BGM.play(CUSTOMENV.bgm) + BG.set(CUSTOMGAME_LOCAL.customenv.bg) + BGM.play(CUSTOMGAME_LOCAL.customenv.bgm) end elseif key=='f1' then SCN.go('mod','swipeD') elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then - local str="Techmino Quest:"..DATA.copyQuestArgs().."!" - if #BAG>0 then str=str..DATA.copySequence() end + local str="Techmino Quest:"..DATA.copyQuestArgs(CUSTOMGAME_LOCAL.customenv).."!" + if #CUSTOMGAME_LOCAL.bag>0 then str=str..DATA.copySequence(CUSTOMGAME_LOCAL.bag) end str=str.."!" - if #MISSION>0 then str=str..DATA.copyMission() end - sys.setClipboardText(str.."!"..DATA.copyBoards().."!") + if #CUSTOMGAME_LOCAL.mission>0 then str=str..DATA.copyMission(CUSTOMGAME_LOCAL.mission) end + sys.setClipboardText(str.."!"..DATA.copyBoards(CUSTOMGAME_LOCAL.field).."!") MES.new('check',text.exportSuccess) elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then local str=sys.getClipboardText() local args=str:sub((str:find(":") or 0)+1):split("!") repeat if #args<4 then break end-- goto THROW_fail - if not ( - DATA.pasteQuestArgs(args[1]) and - DATA.pasteSequence(args[2]) and - DATA.pasteMission(args[3]) - ) then break end-- goto THROW_fail - TABLE.cut(FIELD) - FIELD[1]=DATA.newBoard() + local success,env=DATA.pasteQuestArgs(args[1]) + if not success then break end-- goto THROW_fail + TABLE.cover(env,CUSTOMGAME_LOCAL.customenv) + + local success,bag=DATA.pasteSequence(args[2]) + if not success then break end-- goto THROW_fail + CUSTOMGAME_LOCAL.bag=bag + + local success,mission=DATA.pasteMission(args[3]) + if not success then break end-- goto THROW_fail + CUSTOMGAME_LOCAL.mission=mission + + TABLE.cut(CUSTOMGAME_LOCAL.field) + CUSTOMGAME_LOCAL.field[1]=DATA.newBoard() for i=4,#args do - if args[i]:find("%S") and not DATA.pasteBoard(args[i],i-3) and i<#args then break end-- goto THROW_fail + if args[i]:find("%S") then + local success,F=DATA.pasteBoard(args[i]) + if success then + CUSTOMGAME_LOCAL.field[i-3]=F + else + if i<#args then break end-- goto THROW_fail + end + end end MES.new('check',text.importSuccess) return @@ -133,20 +208,20 @@ function scene.draw() setFont(30) -- Sequence - if #MISSION>0 then - gc.setColor(1,CUSTOMENV.missionKill and 0 or 1,floor(TIME()*6.26)%2) - gc.print("#"..#MISSION,70,220) + if #CUSTOMGAME_LOCAL.mission>0 then + gc.setColor(1,CUSTOMGAME_LOCAL.customenv.missionKill and 0 or 1,floor(TIME()*6.26)%2) + gc.print("#"..#CUSTOMGAME_LOCAL.mission,70,220) end -- Field content - if #FIELD[1]>0 then + if #CUSTOMGAME_LOCAL.field[1]>0 then gc.push('transform') gc.translate(330,240) gc.scale(.5) gc.setColor(1,1,1) gc.setLineWidth(3) gc.rectangle('line',-2,-2,304,604) - local F=FIELD[1] + local F=CUSTOMGAME_LOCAL.field[1] local cross=TEXTURE.puzzleMark[-1] local texture=SKIN.lib[SETTING.skinSet] for y=1,#F do for x=1,10 do @@ -158,19 +233,19 @@ function scene.draw() end end end gc.pop() - if #FIELD>1 then + if #CUSTOMGAME_LOCAL.field>1 then gc.setColor(1,1,floor(TIME()*6.26)%2) - gc.print("+"..#FIELD-1,490,220) + gc.print("+"..#CUSTOMGAME_LOCAL.field-1,490,220) end end -- Sequence - if #BAG>0 then + if #CUSTOMGAME_LOCAL.bag>0 then gc.setColor(1,1,floor(TIME()*6.26)%2) - gc.print("#"..#BAG,615,220) + gc.print("#"..#CUSTOMGAME_LOCAL.bag,615,220) end gc.setColor(COLOR.Z) - gc.print(CUSTOMENV.sequence,610,250) + gc.print(CUSTOMGAME_LOCAL.customenv.sequence,610,250) -- Mod indicator if modUsed then @@ -193,8 +268,8 @@ scene.widgetList={ WIDGET.newKey{name='field', x=450,y=180,w=240,h=80,color='A',font=25,code=pressKey'f'}, WIDGET.newKey{name='sequence', x=730,y=180,w=240,h=80,color='W',font=25,code=pressKey's'}, - WIDGET.newText{name='noMsn', x=50, y=220,align='L',color='H',hideF=function() return MISSION[1] end}, - WIDGET.newText{name='defSeq', x=610,y=220,align='L',color='H',hideF=function() return BAG[1] end}, + WIDGET.newText{name='noMsn', x=50, y=220,align='L',color='H',hideF=function() return CUSTOMGAME_LOCAL.mission[1] end}, + WIDGET.newText{name='defSeq', x=610,y=220,align='L',color='H',hideF=function() return CUSTOMGAME_LOCAL.bag[1] end}, -- Selectors WIDGET.newSelector{name='opponent', x=170,y=330,w=260,color='R',list=sList.opponent, disp=CUSval('opponent'), code=CUSsto('opponent')}, @@ -219,7 +294,7 @@ scene.widgetList={ WIDGET.newButton{name='copy', x=1070,y=300,w=310,h=70,color='lR',font=25,code=pressKey'cC'}, WIDGET.newButton{name='paste', x=1070,y=380,w=310,h=70,color='lB',font=25,code=pressKey'cV'}, WIDGET.newButton{name='play_clear', x=1070,y=460,w=310,h=70,color='lY',font=35,code=pressKey'play1'}, - WIDGET.newButton{name='play_puzzle', x=1070,y=540,w=310,h=70,color='lM',font=35,code=pressKey'play2',hideF=function() return #FIELD[1]==0 end}, + WIDGET.newButton{name='play_puzzle', x=1070,y=540,w=310,h=70,color='lM',font=35,code=pressKey'play2',hideF=function() return #CUSTOMGAME_LOCAL.field[1]==0 end}, WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=pressKey'escape'}, -- Ruleset @@ -235,15 +310,15 @@ scene.widgetList={ WIDGET.newSwitch{name='bone', x=1170,y=970, lim=250,disp=CUSval('bone'), code=CUSrev('bone')}, -- Next & Hold - WIDGET.newSelector{name='holdMode', x=310, y=890, w=300,color='lY',list=sList.holdMode,disp=CUSval('holdMode'),code=CUSsto('holdMode'),hideF=function() return CUSTOMENV.holdCount==0 end}, + WIDGET.newSelector{name='holdMode', x=310, y=890, w=300,color='lY',list=sList.holdMode,disp=CUSval('holdMode'),code=CUSsto('holdMode'),hideF=function() return CUSTOMGAME_LOCAL.customenv.holdCount==0 end}, WIDGET.newSlider{name='nextCount', x=140, y=960, lim=130,w=180,axis={0,6,1},disp=CUSval('nextCount'),code=CUSsto('nextCount')}, WIDGET.newSlider{name='holdCount', x=140, y=1030,lim=130,w=180,axis={0,6,1},disp=CUSval('holdCount'),code=CUSsto('holdCount')}, - WIDGET.newSwitch{name='infHold', x=560, y=960, lim=200, disp=CUSval('infHold'),code=CUSrev('infHold'),hideF=function() return CUSTOMENV.holdCount==0 end}, - WIDGET.newSwitch{name='phyHold', x=560, y=1030,lim=200, disp=CUSval('phyHold'),code=CUSrev('phyHold'),hideF=function() return CUSTOMENV.holdCount==0 end}, + WIDGET.newSwitch{name='infHold', x=560, y=960, lim=200, disp=CUSval('infHold'),code=CUSrev('infHold'),hideF=function() return CUSTOMGAME_LOCAL.customenv.holdCount==0 end}, + WIDGET.newSwitch{name='phyHold', x=560, y=1030,lim=200, disp=CUSval('phyHold'),code=CUSrev('phyHold'),hideF=function() return CUSTOMGAME_LOCAL.customenv.holdCount==0 end}, -- BG & BGM - WIDGET.newSelector{name='bg', x=840, y=1100,w=250,color='Y',list=BG.getList(),disp=CUSval('bg'),code=function(i) CUSTOMENV.bg=i BG.set(i) end}, - WIDGET.newSelector{name='bgm', x=1120,y=1100,w=250,color='Y',list=BGM.getList(),disp=CUSval('bgm'),code=function(i) CUSTOMENV.bgm=i BGM.play(i) end}, + WIDGET.newSelector{name='bg', x=840, y=1100,w=250,color='Y',list=BG.getList(),disp=CUSval('bg'),code=function(i) CUSTOMGAME_LOCAL.customenv.bg=i BG.set(i) end}, + WIDGET.newSelector{name='bgm', x=1120,y=1100,w=250,color='Y',list=BGM.getList(),disp=CUSval('bgm'),code=function(i) CUSTOMGAME_LOCAL.customenv.bgm=i BGM.play(i) end}, } return scene diff --git a/parts/scenes/custom_field.lua b/parts/scenes/custom_field.lua index ecfad3c9..231f2eeb 100644 --- a/parts/scenes/custom_field.lua +++ b/parts/scenes/custom_field.lua @@ -4,7 +4,7 @@ local kb=love.keyboard local max,min,floor=math.max,math.min,math.floor local ins,rem=table.insert,table.remove -local FIELD=FIELD +local FIELD=CUSTOMGAME_LOCAL.field local scene={} local curPen @@ -125,7 +125,7 @@ function scene.enter() page=1 end function scene.leave() - saveFile(DATA.copyBoards(),'conf/customBoards') + saveFile(DATA.copyBoards(FIELD),'conf/customBoards') end function scene.mouseMove(x,y) @@ -226,7 +226,7 @@ function scene.keyDown(key) SFX.play('clear_4',.8) SFX.play('fall',.8) elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then - sys.setClipboardText("Techmino Field:"..DATA.copyBoard(page)) + sys.setClipboardText("Techmino Field:"..DATA.copyBoard(FIELD[page])) MES.new('check',text.exportSuccess) elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then local str=sys.getClipboardText() @@ -237,7 +237,9 @@ function scene.keyDown(key) end str=str:sub(p+1) end - if DATA.pasteBoard(str,page) then + local success,F=DATA.pasteBoard(str) + if success then + FIELD[page]=F MES.new('check',text.importSuccess) else MES.new('error',text.dataCorrupted) diff --git a/parts/scenes/custom_mission.lua b/parts/scenes/custom_mission.lua index d432da72..ad5620be 100644 --- a/parts/scenes/custom_mission.lua +++ b/parts/scenes/custom_mission.lua @@ -5,6 +5,7 @@ local floor,sin=math.floor,math.sin local ins,rem=table.insert,table.remove local scene={} +local MISSION=CUSTOMGAME_LOCAL.mission local input-- Input buffer local cur-- Cursor position @@ -14,7 +15,7 @@ function scene.enter() cur=#MISSION end function scene.leave() - saveFile(DATA.copyMission(),'conf/customMissions') + saveFile(DATA.copyMission(MISSION),'conf/customMissions') end local ENUM_MISSION=ENUM_MISSION @@ -67,7 +68,7 @@ function scene.keyDown(key) end elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then if #MISSION>0 then - sys.setClipboardText("Techmino Target:"..DATA.copyMission()) + sys.setClipboardText("Techmino Target:"..DATA.copyMission(MISSION)) MES.new('check',text.exportSuccess) end elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then @@ -79,7 +80,9 @@ function scene.keyDown(key) end str=str:sub(p+1) end - if DATA.pasteMission(str) then + local success,mission=DATA.pasteMission(str) + if success then + CUSTOMGAME_LOCAL.mission=mission MES.new('check',text.importSuccess) cur=#MISSION else @@ -222,7 +225,7 @@ scene.widgetList={ WIDGET.newKey{name='reset', x=1000,y=640,w=90, color='lY',font=50,code=pressKey'delete', fText=CHAR.icon.trash}, WIDGET.newButton{name='copy', x=1140,y=440,w=170,h=80,color='lR',font=50,code=pressKey'cC', fText=CHAR.icon.export,hideF=function() return #MISSION==0 end}, WIDGET.newButton{name='paste', x=1140,y=540,w=170,h=80,color='lB',font=50,code=pressKey'cV', fText=CHAR.icon.import}, - WIDGET.newSwitch{name='mission',x=1150,y=340,lim=280,disp=CUSval('missionKill'),code=CUSrev('missionKill')}, + WIDGET.newSwitch{name='mission',x=1150,y=340,lim=280,disp=CUSTOMGAME_LOCAL:CUSval('missionKill'),code=CUSTOMGAME_LOCAL:CUSrev('missionKill')}, WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=backScene}, } diff --git a/parts/scenes/custom_sequence.lua b/parts/scenes/custom_sequence.lua index dbf2c0e7..db966d77 100644 --- a/parts/scenes/custom_sequence.lua +++ b/parts/scenes/custom_sequence.lua @@ -6,6 +6,7 @@ local ins,rem=table.insert,table.remove local gc_setColor,gc_print=GC.setColor,GC.print local scene={} +local BAG=CUSTOMGAME_LOCAL.bag local cur-- Cursor position @@ -13,7 +14,7 @@ function scene.enter() cur=#BAG end function scene.leave() - saveFile(DATA.copySequence(),'conf/customSequence') + saveFile(DATA.copySequence(BAG),'conf/customSequence') end local minoKey={ @@ -75,7 +76,7 @@ function scene.keyDown(key) scene.widgetList.sequence:scroll(kb.isDown('lshift','rshift') and -1 or 1) elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then if #BAG>0 then - sys.setClipboardText("Techmino SEQ:"..DATA.copySequence()) + sys.setClipboardText("Techmino SEQ:"..DATA.copySequence(BAG)) MES.new('check',text.exportSuccess) end elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then @@ -87,7 +88,9 @@ function scene.keyDown(key) end str=str:sub(p+1) end - if DATA.pasteSequence(str) then + local success,bag=DATA.pasteSequence(str) + if success then + CUSTOMGAME_LOCAL.bag=bag MES.new('check',text.importSuccess) cur=#BAG else @@ -175,7 +178,7 @@ scene.widgetList={ WIDGET.newSelector{name='sequence',x=1080,y=60,w=200,color='Y', list={'bag','bagES','his','hisPool','c2','bagP1inf','rnd','mess','reverb','loop','fixed'}, - disp=CUSval('sequence'),code=CUSsto('sequence') + disp=CUSTOMGAME_LOCAL:CUSval('sequence'),code=CUSTOMGAME_LOCAL:CUSsto('sequence') }, WIDGET.newKey{name='Z', x=120,y=460,w=80,font=90,fText=CHAR.mino.Z,code=pressKey(1)}, diff --git a/parts/scenes/net_newRoom.lua b/parts/scenes/net_newRoom.lua index 2c067345..84e7055b 100644 --- a/parts/scenes/net_newRoom.lua +++ b/parts/scenes/net_newRoom.lua @@ -106,7 +106,7 @@ scene.widgetList={ WIDGET.newSelector{name='eventSet', x=1050,y=760,w=340,color='H',list=sList.eventSet,disp=ROOMval('eventSet'),code=ROOMval('eventSet')}, -- Next & Hold - WIDGET.newSelector{name='holdMode', x=310, y=890, w=300,color='lY',list=sList.holdMode,disp=ROOMval('holdMode'),code=ROOMval('holdMode'),hideF=function() return CUSTOMENV.holdCount==0 end}, + WIDGET.newSelector{name='holdMode', x=310, y=890, w=300,color='lY',list=sList.holdMode,disp=ROOMval('holdMode'),code=ROOMval('holdMode'),hideF=function() return ROOMENV.holdCount==0 end}, WIDGET.newSlider{name='nextCount', x=140, y=960, lim=130,w=200,axis={0,6,1},disp=ROOMval('nextCount'),code=ROOMsto('nextCount')}, WIDGET.newSlider{name='holdCount', x=140, y=1030,lim=130,w=200,axis={0,6,1},disp=ROOMval('holdCount'),code=ROOMsto('holdCount')}, WIDGET.newSwitch{name='infHold', x=560, y=960, lim=200, disp=ROOMval('infHold'),code=ROOMrev('infHold'),hideF=function() return ROOMENV.holdCount==0 end}, diff --git a/parts/scenes/pause.lua b/parts/scenes/pause.lua index 78e5edcd..d7ca7f8b 100644 --- a/parts/scenes/pause.lua +++ b/parts/scenes/pause.lua @@ -138,13 +138,13 @@ function scene.keyDown(key,isRep) SCN.swapTo('game','none') end elseif key=='p' then - if (GAME.result or GAME.replaying) and #PLAYERS==1 then + if (GAME.result or GAME.replaying) and GAME.initPlayerCount==1 then resetGameData('r') PLAYERS[1]:startStreaming(GAME.rep) SCN.swapTo('game','none') end elseif key=='o' then - if (GAME.result or GAME.replaying) and #PLAYERS==1 and not GAME.saved then + if (GAME.result or GAME.replaying) and GAME.initPlayerCount==1 and not GAME.saved then if DATA.saveReplay() then GAME.saved=true SFX.play('connected') @@ -359,8 +359,8 @@ scene.widgetList={ fShade=GC.DO{70,70,{'setCL',1,1,1,.4},{'draw',GC.DO{70,70,{'setCL',1,1,1,1},{'fRRPol',37,35,32,3,6},{'fRRPol',25,35,32,3,6}}}}, hideF=function() return PLAYERS[1].frameRun<=180 end, }, - WIDGET.newKey{name='replay', x=865,y=165,w=200,h=40,font=25,code=pressKey'p',hideF=function() return not (GAME.result or GAME.replaying) or #PLAYERS>1 end}, - WIDGET.newKey{name='save', x=1075,y=165,w=200,h=40,font=25,code=pressKey'o',hideF=function() return not (GAME.result or GAME.replaying) or #PLAYERS>1 or GAME.saved end}, + WIDGET.newKey{name='replay', x=865,y=165,w=200,h=40,font=25,code=pressKey'p',hideF=function() return not (GAME.result or GAME.replaying) or GAME.initPlayerCount>1 end}, + WIDGET.newKey{name='save', x=1075,y=165,w=200,h=40,font=25,code=pressKey'o',hideF=function() return not (GAME.result or GAME.replaying) or GAME.initPlayerCount>1 or GAME.saved end}, } return scene diff --git a/parts/scenes/replays.lua b/parts/scenes/replays.lua index dcf83314..3d8473b3 100644 --- a/parts/scenes/replays.lua +++ b/parts/scenes/replays.lua @@ -52,6 +52,9 @@ local function _playRep(fileName) DATA.pumpRecording(rep.data,GAME.rep) loadGame(rep.mode,true) + if rep.private and GAME.curMode.loadPrivate then + GAME.curMode.loadPrivate(rep.private) + end resetGameData('r') PLAYERS[1].username=rep.player PLAYERS[1]:startStreaming(GAME.rep)