联网对战测试推进22

This commit is contained in:
MrZ626
2021-02-06 13:23:52 +08:00
parent 38d3e4477c
commit eec05e7eb6
18 changed files with 350 additions and 105 deletions

View File

@@ -539,6 +539,28 @@ function initPlayerPosition(sudden)--Set initial position for every player
error("TOO MANY PLAYERS!") error("TOO MANY PLAYERS!")
end end
end end
do--function dumpBasicConfig()
local gameSetting={
--Tuning
"das","arr","dascut","sddas","sdarr",
"ihs","irs","ims","RS","swap",
--System
"skin","face",
--Graphic
"block","ghost","center","smooth","grid","bagLine",
"lockFX","dropFX","moveFX","clearFX","splashFX","shakeFX","atkFX",
"text","score","warn","highCam","nextPos",
}
function dumpBasicConfig()
local S={}
for _,key in next,gameSetting do
S[key]=SETTING[key]
end
return data.encode("string","base64",json.encode(S))
end
end
do--function resetGameData(args) do--function resetGameData(args)
local function tick_showMods() local function tick_showMods()
local time=0 local time=0
@@ -579,7 +601,7 @@ do--function resetGameData(args)
end end
return S return S
end end
function resetGameData(args,playerData) function resetGameData(args,playerData,seed)
if not args then args=""end if not args then args=""end
if PLAYERS[1]and not GAME.replaying and(GAME.frame>400 or GAME.result)then if PLAYERS[1]and not GAME.replaying and(GAME.frame>400 or GAME.result)then
mergeStat(STAT,PLAYERS[1].stat) mergeStat(STAT,PLAYERS[1].stat)
@@ -595,7 +617,7 @@ do--function resetGameData(args)
GAME.replaying=1 GAME.replaying=1
else else
GAME.frame=args:find("n")and 0 or 150-SETTING.reTime*15 GAME.frame=args:find("n")and 0 or 150-SETTING.reTime*15
GAME.seed=rnd(1046101471,2662622626) GAME.seed=seed or rnd(1046101471,2662622626)
GAME.pauseTime=0 GAME.pauseTime=0
GAME.pauseCount=0 GAME.pauseCount=0
GAME.saved=false GAME.saved=false
@@ -650,28 +672,33 @@ function gameStart()--Call when countdown finish (GAME.frame==180)
end end
--[[ --[[
Table data format:
{frame,event, frame,event, ...}
Byte data format: (1 byte each period) Byte data format: (1 byte each period)
KeyID, dt, KeyID, dt, ...... dt, event, dt, event, ...
KeyID range from 1 to 20, negative when release key event range from 1 to 20, negative when release key
dt from 0 to infinity, 0~254 when 0~254, read next byte as dt(if there is an 255, add next byte to dt as well) dt from 0 to infinity, 0~254 when 0~254, read next byte as dt(if there is an 255, add next byte to dt as well)
Example: Example:
1,6, -1,20, 2,0, -2,255,0, 4,255,255,255,62, ...... 6,1, 20,-1, 0,2, 255,0,-2, 255,255,255,62,4 ...
Translate:
(6,1)(20,-1)(0,2)(255,0,-2)(255,255,255,62,4) ...
This means: This means:
Press key1 at 6f Press key1 at 6f
Release key1 at 26f (6+20) Release key1 at 26f (6+20)
Press key2 at the same time(26+0) Press key2 at the same time (26+0)
Release key 2 after 255+0 frame Release key 2 after 255+0 frame (26+0+255+0)
Press key 4 after 255+255+255+62 frame Press key 4 after 255+255+255+62 frame (26+0+255+0+255+255+255+62)
...... ...
]] ]]
function dumpRecording(list,ptr) function dumpRecording(list,ptr)
local out="" local out=""
local buffer="" local buffer=""
local prevFrm=0 if not ptr then ptr=1 end
ptr=ptr or 1 local prevFrm=list[ptr-2]or 0
while list[ptr]do while list[ptr]do
--Check buffer size --Flush buffer
if #buffer>10 then if #buffer>10 then
out=out..buffer out=out..buffer
buffer="" buffer=""
@@ -686,14 +713,18 @@ function dumpRecording(list,ptr)
end end
buffer=buffer..char(t) buffer=buffer..char(t)
--Encode key --Encode event
t=list[ptr+1] t=list[ptr+1]
buffer=buffer..char(t>0 and t or 256+t) while t>=255 do
buffer=buffer.."\255"
t=t-255
end
buffer=buffer..char(t)
--Step --Step
ptr=ptr+2 ptr=ptr+2
end end
return out..buffer return out..buffer,ptr
end end
function pumpRecording(str,L) function pumpRecording(str,L)
local len=#str local len=#str
@@ -702,22 +733,27 @@ function pumpRecording(str,L)
local curFrm=L[#L-1]or 0 local curFrm=L[#L-1]or 0
while p<=len do while p<=len do
--Read delta time --Read delta time
::nextByte:: ::nextByte1::
local b=byte(str,p) local b=byte(str,p)
if b==255 then if b==255 then
curFrm=curFrm+255 curFrm=curFrm+255
p=p+1 p=p+1
goto nextByte goto nextByte1
end end
curFrm=curFrm+b curFrm=curFrm+b
L[#L+1]=curFrm L[#L+1]=curFrm
p=p+1 p=p+1
::nextByte2::
b=byte(str,p) b=byte(str,p)
if b>127 then local event=0
b=b-256 if b==255 then
event=event+255
p=p+1
goto nextByte2
end end
L[#L+1]=b event=event+b
L[#L+1]=event
p=p+1 p=p+1
end end
end end
@@ -840,6 +876,34 @@ function TICK_httpREQ_getAccessToken(task)
end end
end end
end end
function TICK_httpREQ_getUserInfo(task)
local time=0
while true do
coroutine.yield()
local response,request_error=client.poll(task)
if response then
local res=json.decode(response.body)
if response.code==200 and res.message=="OK"then
-- LOG.print(text.accessSuccessed)
USER.username=res.username
USER.motto=res.motto
USER.avatar=res.avatar
FILE.save(USER,"conf/user")
else
-- LOG.print(text.loginFailed..": "..text.httpCode..response.code.."-"..res.message,"warn")
end
return
elseif request_error then
LOG.print(text.loginFailed..": "..request_error,"warn")
return
end
time=time+1
if time>360 then
LOG.print(text.loginFailed..": "..text.httpTimeout,"message")
return
end
end
end
function TICK_wsRead() function TICK_wsRead()
while true do while true do
coroutine.yield() coroutine.yield()

View File

@@ -245,16 +245,15 @@ GAME={--Global game data
RANKS=FILE.load("conf/unlock")or{sprint_10l=0}--Ranks of modes RANKS=FILE.load("conf/unlock")or{sprint_10l=0}--Ranks of modes
USER=FILE.load("conf/user")or{--User infomation USER=FILE.load("conf/user")or{--User infomation
--Network infos --Network infos
name=false, username=false,
id=false, id=false,
email=false, email=false,
motto=false,
avatar=false,
auth_token=false, auth_token=false,
access_token=false, access_token=false,
--Local data --Local data
username=false,
motto=false,
avatar=false,
xp=0,lv=1, xp=0,lv=1,
} }
SETTING={--Settings SETTING={--Settings

View File

@@ -94,8 +94,8 @@ return{
wsError="WebSocket error: ", wsError="WebSocket error: ",
waitNetTask="Connecting, please wait", waitNetTask="Connecting, please wait",
chatJoin="joined the room.", joinRoom="joined the room.",
chatLeave="left the room.", leaveRoom="left the room.",
chatRemain="Online: ", chatRemain="Online: ",
chatStart="------Beginning of log------", chatStart="------Beginning of log------",
chatHistory="------New messages below------", chatHistory="------New messages below------",

View File

@@ -96,8 +96,8 @@ return{
-- wsError="WebSocket error: ", -- wsError="WebSocket error: ",
-- waitNetTask="Connecting, please wait", -- waitNetTask="Connecting, please wait",
-- chatJoin="joined the room.", -- joinRoom="joined the room.",
-- chatLeave="left the room.", -- leaveRoom="left the room.",
-- chatRemain="Online: ", -- chatRemain="Online: ",
-- chatStart="------Beginning of log------", -- chatStart="------Beginning of log------",
-- chatHistory="------New messages below------", -- chatHistory="------New messages below------",
@@ -182,7 +182,7 @@ return{
simple-love-lights [dylhunn] simple-love-lights [dylhunn]
]], ]],
support="Aider le créateur", support="Aider le créateur",
group="Groupe QQ officiel (si non piraté) : 1127702001", group="Groupe QQ officiel (si non piraté) : 913154753",
WidgetText={ WidgetText={
main={ main={
-- offline="Single", -- offline="Single",

View File

@@ -94,8 +94,8 @@ return{
wsError="WebSocket error: ", wsError="WebSocket error: ",
waitNetTask="Conectando, aguarde", waitNetTask="Conectando, aguarde",
chatJoin="Entrou a sala.", joinRoom="Entrou a sala.",
chatLeave="Saiu da sala.", leaveRoom="Saiu da sala.",
chatRemain="Online: ", chatRemain="Online: ",
chatStart="------Começo do log------", chatStart="------Começo do log------",
chatHistory="------Novas mensagens abaixo------", chatHistory="------Novas mensagens abaixo------",

View File

@@ -97,8 +97,8 @@ return{
-- wsError="WebSocket error: ", -- wsError="WebSocket error: ",
-- waitNetTask="Connecting, please wait", -- waitNetTask="Connecting, please wait",
-- chatJoin="joined the room.", -- joinRoom="joined the room.",
-- chatLeave="left the room.", -- leaveRoom="left the room.",
-- chatRemain="Online: ", -- chatRemain="Online: ",
-- chatStart="------Beginning of log------", -- chatStart="------Beginning of log------",
-- chatHistory="------New messages below------", -- chatHistory="------New messages below------",
@@ -184,7 +184,7 @@ return{
simple-love-lights [dylhunn] simple-love-lights [dylhunn]
]], ]],
support="Apoyen al Autor", support="Apoyen al Autor",
group="Grupo Oficial de QQ (si no lo hackean):1127702001", group="Grupo Oficial de QQ (si no lo hackean) : 913154753",
WidgetText={ WidgetText={
main={ main={
-- offline="Single", -- offline="Single",

View File

@@ -86,8 +86,8 @@ return{
registerFailed="注册失败", registerFailed="注册失败",
loginSuccessed="登录成功", loginSuccessed="登录成功",
loginFailed="登录失败", loginFailed="登录失败",
accessSuccessed="授权成功", accessSuccessed="身份验证成功",
accessFailed="授权失败", accessFailed="身份验证失败",
wsSuccessed="WS连接成功", wsSuccessed="WS连接成功",
wsFailed="WS连接失败", wsFailed="WS连接失败",
wsDisconnected="WS连接断开", wsDisconnected="WS连接断开",
@@ -95,8 +95,8 @@ return{
wsError="WS错误: ", wsError="WS错误: ",
waitNetTask="正在连接,请稍候", waitNetTask="正在连接,请稍候",
chatJoin="进入房间", joinRoom="进入房间",
chatLeave="离开房间", leaveRoom="离开房间",
chatRemain="人数:", chatRemain="人数:",
chatStart="------消息的开头------", chatStart="------消息的开头------",
chatHistory="------以上是历史消息------", chatHistory="------以上是历史消息------",
@@ -205,7 +205,7 @@ return{
simple-love-lights [dylhunn] simple-love-lights [dylhunn]
]], ]],
support="支持作者", support="支持作者",
group="官方QQ群(如果没有被暗改的话就是这个):1127702001", group="官方QQ群(如果没有被暗改的话就是这个):913154753",
WidgetText={ WidgetText={
main={ main={
offline="单机游戏", offline="单机游戏",

View File

@@ -7,10 +7,8 @@ return{
PLY.newPlayer(1) PLY.newPlayer(1)
local N=2 local N=2
for i=1,#playerData do for i=1,#playerData do
if playerData[i].id~=USER.id then PLY.newRemotePlayer(N,false,playerData[i])
PLY.newRemotePlayer(N,false,playerData[i]) N=N+1
N=N+1
end
end end
end, end,
} }

View File

@@ -349,6 +349,11 @@ function draw.norm(P)
--Field-related things --Field-related things
gc_push("transform") gc_push("transform")
gc_translate(150,0) gc_translate(150,0)
if P.userName then
setFont(30)
gc_setColor(1,1,1)
mStr(P.userName,150,-60)
end
--Things shake with field --Things shake with field
gc_push("transform") gc_push("transform")

View File

@@ -50,8 +50,9 @@ local function releaseKey(P,keyID)
end end
local function pressKey_Rec(P,keyID) local function pressKey_Rec(P,keyID)
if P.keyAvailable[keyID]and P.alive then if P.keyAvailable[keyID]and P.alive then
ins(GAME.rep,GAME.frame+1) local L=GAME.rep
ins(GAME.rep,keyID) ins(L,GAME.frame+1)
ins(L,keyID)
P.keyPressing[keyID]=true P.keyPressing[keyID]=true
P.actList[keyID](P) P.actList[keyID](P)
if P.control then if P.control then
@@ -64,8 +65,9 @@ local function pressKey_Rec(P,keyID)
end end
end end
local function releaseKey_Rec(P,keyID) local function releaseKey_Rec(P,keyID)
ins(GAME.rep,GAME.frame+1) local L=GAME.rep
ins(GAME.rep,-keyID) ins(L,GAME.frame+1)
ins(L,32+keyID)
P.keyPressing[keyID]=false P.keyPressing[keyID]=false
end end
local function newEmptyPlayer(id,mini) local function newEmptyPlayer(id,mini)
@@ -186,8 +188,7 @@ end
local function loadGameEnv(P)--Load gameEnv local function loadGameEnv(P)--Load gameEnv
P.gameEnv={}--Current game setting environment P.gameEnv={}--Current game setting environment
local ENV=P.gameEnv local ENV=P.gameEnv
local GAME=GAME local GAME,SETTING=GAME,SETTING
local SETTING=SETTING
--Load game settings --Load game settings
for k,v in next,gameEnv0 do for k,v in next,gameEnv0 do
if GAME.modeEnv[k]~=nil then if GAME.modeEnv[k]~=nil then
@@ -214,6 +215,26 @@ local function loadGameEnv(P)--Load gameEnv
end end
end end
end end
local function loadRemoteEnv(P,conf)--Load gameEnv
P.gameEnv={}--Current game setting environment
local ENV=P.gameEnv
local GAME,SETTING=GAME,SETTING
--Load game settings
for k,v in next,gameEnv0 do
if GAME.modeEnv[k]~=nil then
v=GAME.modeEnv[k] --Mode setting
elseif conf[k]~=nil then
v=conf[k] --Game setting
elseif SETTING[k]~=nil then
v=SETTING[k] --Global setting
end
if type(v)~="table"then--Default setting
ENV[k]=v
else
ENV[k]=copyTable(v)
end
end
end
local function applyGameEnv(P)--Finish gameEnv processing local function applyGameEnv(P)--Finish gameEnv processing
local ENV=P.gameEnv local ENV=P.gameEnv
@@ -332,16 +353,19 @@ function PLY.newDemoPlayer(id)
} }
P:popNext() P:popNext()
end end
function PLY.newRemotePlayer(id,mini,userInfo) function PLY.newRemotePlayer(id,mini,playerData)
local P=newEmptyPlayer(id,mini) local P=newEmptyPlayer(id,mini)
P.type="remote" P.type="remote"
P.update=PLY.update.remote_alive P.update=PLY.update.remote_alive
P.userName=userInfo.name
P.userID=userInfo.id
P.stream={} P.stream={}
P.streamProgress=1 P.streamProgress=1
loadGameEnv(P) playerData.p=P
P.userName=playerData.name
P.userID=playerData.id
loadRemoteEnv(P,playerData.conf or{})
applyGameEnv(P) applyGameEnv(P)
prepareSequence(P) prepareSequence(P)
end end

View File

@@ -224,6 +224,14 @@ function Player.setRS(P,RSname)
P.RS=kickList[RSname] P.RS=kickList[RSname]
end end
function Player.setConf(P,conf)
for k,v in next,conf do
if not GAME.modeEnv[k]then
P.gameEnv[k]=v
end
end
end
function Player.getHolePos(P)--Get a good garbage-line hole position function Player.getHolePos(P)--Get a good garbage-line hole position
if P.garbageBeneath==0 then if P.garbageBeneath==0 then
return P:RND(10) return P:RND(10)
@@ -332,9 +340,21 @@ function Player.attack(P,R,send,time,...)
if SETTING.atkFX>0 then if SETTING.atkFX>0 then
P:createBeam(R,send,time,...) P:createBeam(R,send,time,...)
end end
R.lastRecv=P if GAME.net then
if R.atkBuffer.sum<26 then if P.type=="human"then
local B=R.atkBuffer --TODO
end
if R.type=="human"then
--TODO
end
else
R:receive(P,send,time)
end
end
function Player.receive(P,A,send,time)
P.lastRecv=A
local B=P.atkBuffer
if B.sum<26 then
if send>26-B.sum then send=26-B.sum end if send>26-B.sum then send=26-B.sum end
local m,k=#B,1 local m,k=#B,1
while k<=m and time>B[k].countdown do k=k+1 end while k<=m and time>B[k].countdown do k=k+1 end
@@ -342,7 +362,7 @@ function Player.attack(P,R,send,time,...)
B[i+1]=B[i] B[i+1]=B[i]
end end
B[k]={ B[k]={
pos=P:RND(10), pos=A:RND(10),
amount=send, amount=send,
countdown=time, countdown=time,
cd0=time, cd0=time,
@@ -351,8 +371,8 @@ function Player.attack(P,R,send,time,...)
lv=min(int(send^.69),5), lv=min(int(send^.69),5),
}--Sorted insert(by time) }--Sorted insert(by time)
B.sum=B.sum+send B.sum=B.sum+send
R.stat.recv=R.stat.recv+send P.stat.recv=P.stat.recv+send
if R.sound then if P.sound then
SFX.play(send<4 and"blip_1"or"blip_2",min(send+1,5)*.1) SFX.play(send<4 and"blip_1"or"blip_2",min(send+1,5)*.1)
end end
end end

View File

@@ -1,4 +1,5 @@
local int,max,min,abs=math.floor,math.max,math.min,math.abs local max,min=math.max,math.min
local int,abs,rnd=math.floor,math.abs,math.random
local rem=table.remove local rem=table.remove
local function updateLine(P)--Attacks, line pushing, cam moving local function updateLine(P)--Attacks, line pushing, cam moving
@@ -108,7 +109,9 @@ local updateTasks do--updateTasks(P)
end end
end end
local function update_alive(P,dt) local update={
}
function update.alive(P,dt)
local ENV=P.gameEnv local ENV=P.gameEnv
if P.timing then if P.timing then
local S=P.stat local S=P.stat
@@ -336,10 +339,6 @@ local function update_alive(P,dt)
updateFXs(P,dt) updateFXs(P,dt)
updateTasks(P) updateTasks(P)
end end
local update={
alive=update_alive,
}
function update.dead(P,dt) function update.dead(P,dt)
if P.keyRec then if P.keyRec then
local S=P.stat local S=P.stat
@@ -369,23 +368,41 @@ function update.dead(P,dt)
updateTasks(P) updateTasks(P)
end end
function update.remote_alive(P,dt) function update.remote_alive(P,dt)
local frmStep=GAME.frame-P.stat.frame
frmStep=
frmStep<60 and 1 or
frmStep<120 and rnd(2)or
frmStep<240 and 2 or
frmStep<480 and rnd(2,3) or
3
::readNext:: ::readNext::
local pos=P.streamProgress local pos=P.streamProgress
local tar=P.stream[pos] local eventTime=P.stream[pos]
if tar then if eventTime then
if P.stat.frame==tar then if P.stat.frame==eventTime then
local key=P.stream[pos+1] local key=P.stream[pos+1]
if key>0 then--Press key if key==0 then--Just wait
elseif key<=32 then--Press key
P:pressKey(key) P:pressKey(key)
elseif key<0 then--Release key elseif key<=64 then--Release key
P:releaseKey(-key) P:releaseKey(key-32)
else--Receiving garbage elseif key>1023 then--Receiving garbage
--TODO: local line=key%1024
local amount=int(key/1024)%256
local color=int(key/262144)%256
local sid=int(key/67108864)%256
local time=int(key/17179869184)%256
P:receive()
--TODO
end end
P.streamProgress=pos+2 P.streamProgress=pos+2
goto readNext goto readNext
end end
update_alive(P,dt) update.alive(P,dt)
end
if frmStep>1 then
frmStep=frmStep-1
goto readNext
end end
end end
return update return update

View File

@@ -42,6 +42,16 @@ local function tick_httpREQ_autoLogin(task)
if response.code==200 and res.message=="OK"then if response.code==200 and res.message=="OK"then
LOGIN=true LOGIN=true
LOG.print(text.loginSuccessed) LOG.print(text.loginSuccessed)
httpRequest(
TICK_httpREQ_getUserInfo,
PATH.api..PATH.users,
"GET",
{["Content-Type"]="application/json"},
json.encode{
email=USER.email,
auth_token=USER.auth_token,
}
)
else else
LOGIN=false LOGIN=false
LOG.print(text.loginFailed..": "..text.httpCode..response.code.."-"..res.message,"warn") LOG.print(text.loginFailed..": "..text.httpCode..response.code.."-"..res.message,"warn")

View File

@@ -9,13 +9,21 @@ local function tick_httpREQ_newLogin(task)
LOGIN=true LOGIN=true
USER.email=res.email USER.email=res.email
USER.auth_token=res.auth_token USER.auth_token=res.auth_token
USER.name=res.name
USER.id=res.id USER.id=res.id
USER.motto=res.motto
USER.avatar=res.avatar
FILE.save(USER,"conf/user","q") FILE.save(USER,"conf/user","q")
LOG.print(text.loginSuccessed) LOG.print(text.loginSuccessed)
httpRequest(
TICK_httpREQ_getUserInfo,
PATH.api..PATH.users,
"GET",
{["Content-Type"]="application/json"},
json.encode{
email=USER.email,
auth_token=USER.auth_token,
}
)
httpRequest( httpRequest(
TICK_httpREQ_getAccessToken, TICK_httpREQ_getAccessToken,
PATH.api..PATH.access, PATH.api..PATH.access,

View File

@@ -68,7 +68,7 @@ function scene.socketRead(mes)
textBox:push{ textBox:push{
COLOR.lR,args[1], COLOR.lR,args[1],
COLOR.dY,args[2].." ", COLOR.dY,args[2].." ",
COLOR.Y,text[cmd=="J"and"chatJoin"or"chatLeave"] COLOR.Y,text[cmd=="J"and"joinRoom"or"leaveRoom"]
} }
remain=tonumber(args[3]) remain=tonumber(args[3])
elseif cmd=="T"then elseif cmd=="T"then

View File

@@ -1,3 +1,4 @@
local data=love.data
local gc=love.graphics local gc=love.graphics
local gc_setColor,gc_circle=gc.setColor,gc.circle local gc_setColor,gc_circle=gc.setColor,gc.circle
local tc=love.touch local tc=love.touch
@@ -26,8 +27,15 @@ end
local hideChatBox local hideChatBox
local textBox=WIDGET.newTextBox{name="texts",x=340,y=80,w=600,h=550,hide=function()return hideChatBox end} local textBox=WIDGET.newTextBox{name="texts",x=340,y=80,w=600,h=550,hide=function()return hideChatBox end}
local function switchChat()
hideChatBox=not hideChatBox
end
local playing local playing
local heartBeatTimer
local lastUpstreamTime
local upstreamProgress
local lastBackTime=0 local lastBackTime=0
local noTouch,noKey=false,false local noTouch,noKey=false,false
local touchMoveLastFrame=false local touchMoveLastFrame=false
@@ -38,16 +46,22 @@ function scene.sceneBack()
wsWrite("Q") wsWrite("Q")
WSCONN=false WSCONN=false
LOG.print(text.wsDisconnected,"warn") LOG.print(text.wsDisconnected,"warn")
love.keyboard.setKeyRepeat(true)
end end
function scene.sceneInit() function scene.sceneInit()
love.keyboard.setKeyRepeat(false) love.keyboard.setKeyRepeat(false)
wsWrite("C"..dumpBasicConfig())
TASK.new(TICK_wsRead) TASK.new(TICK_wsRead)
hideChatBox=true hideChatBox=true
textBox:clear() textBox:clear()
playerData={} playerData={}
resetGameData("n",playerData)
noTouch=not SETTING.VKSwitch noTouch=not SETTING.VKSwitch
playing=false playing=false
lastUpstreamTime=0
upstreamProgress=1
heartBeatTimer=0
end end
function scene.touchDown(_,x,y) function scene.touchDown(_,x,y)
@@ -120,6 +134,10 @@ function scene.keyDown(key)
lastBackTime=TIME() lastBackTime=TIME()
LOG.print(text.sureQuit,COLOR.orange) LOG.print(text.sureQuit,COLOR.orange)
end end
elseif key=="b"then
wsWrite("B")
elseif key=="\\"then
switchChat()
else else
if noKey then return end if noKey then return end
local k=keyMap.keyboard[key] local k=keyMap.keyboard[key]
@@ -170,17 +188,18 @@ end
function scene.socketRead(mes) function scene.socketRead(mes)
local cmd=mes:sub(1,1) local cmd=mes:sub(1,1)
local args=splitStr(mes:sub(2),":") local args=splitStr(mes:sub(2),":")
LOG.print(cmd,table.concat(args, " ; "))-------DEBUG PRINT print(cmd.." "..table.concat(args, " ; "))-------DEBUG PRINT
if cmd=="J"or cmd=="L"then if cmd=="J"or cmd=="L"then
textBox:push{ textBox:push{
COLOR.lR,args[1], COLOR.lR,args[1],
COLOR.dY,args[2].." ", COLOR.dY,args[2].." ",
COLOR.Y,text[cmd=="J"and"chatJoin"or"chatLeave"] COLOR.Y,text[cmd=="J"and"joinRoom"or"leaveRoom"]
} }
if cmd=="J"then if cmd=="J"then
ins(playerData,{name=args[1],id=args[2],conf=false}) if tostring(USER.id)~=args[2]then
if not playing then wsWrite("C"..dumpBasicConfig())
resetGameData("n",playerData) ins(playerData,{name=args[1],id=args[2]})
resetGameData("qn",playerData)
end end
else else
for i=1,#playerData do for i=1,#playerData do
@@ -197,8 +216,9 @@ function scene.socketRead(mes)
end end
for i=1,#PLAYERS.alive do for i=1,#PLAYERS.alive do
if PLAYERS.alive[i].userID==args[2]then if PLAYERS.alive[i].userID==args[2]then
rem(PLAYERS,i) rem(PLAYERS.alive,i)
break initPlayerPosition(true)
return
end end
end end
end end
@@ -209,23 +229,36 @@ function scene.socketRead(mes)
COLOR.sky,args[3] COLOR.sky,args[3]
} }
elseif cmd=="C"then elseif cmd=="C"then
for i=1,#playerData do if tostring(USER.id)~=args[2]then
if playerData[i].id==args[1]then local ENV=json.decode(data.decode("string","base64",args[3]))
playerData[i].conf=args[2] for i=1,#playerData do
return if playerData[i].id==args[2]then
playerData[i].conf=ENV
playerData[i].p:setConf(ENV)
return
end
end end
ins(playerData,{name=args[1],id=args[2],conf=ENV})
resetGameData("qn",playerData)
end end
elseif cmd=="S"then elseif cmd=="S"then
for _,P in next,PLAYERS do if args[1]~=tostring(USER.id)then
if P.userID==args[1]then for _,P in next,PLAYERS do
pumpRecording(args[2],P.stream) if P.userID==args[1]then
pumpRecording(data.decode("string","base64",args[2]),P.stream)
end
end end
end end
elseif cmd=="B"then elseif cmd=="B"then
playing=true if not playing then
resetGameData("n",playerData) playing=true
resetGameData("n",playerData,tonumber(args[1]))
else
LOG.print("Redundant signal: B(begin)",30,COLOR.green)
end
elseif cmd=="F"then elseif cmd=="F"then
playing=false playing=false
LOG.print(text.gameover,30,COLOR.green)
else else
LOG.print("Illegal message: ["..mes.."]",30,COLOR.green) LOG.print("Illegal message: ["..mes.."]",30,COLOR.green)
end end
@@ -248,10 +281,27 @@ function scene.update(dt)
end end
end end
if not playing then return end if not playing then
heartBeatTimer=heartBeatTimer+dt
if heartBeatTimer>42 then
heartBeatTimer=0
wsWrite("P")
end
return
end
GAME.frame=GAME.frame+1
if GAME.frame-lastUpstreamTime>10 then
local stream
stream,upstreamProgress=dumpRecording(GAME.rep,upstreamProgress)
if #stream>0 then
wsWrite("S"..data.encode("string","base64",stream))
end
lastUpstreamTime=PLAYERS[1].alive and GAME.frame or 1e99
end
--Counting,include pre-das,directy RETURN,or restart counting --Counting,include pre-das,directy RETURN,or restart counting
GAME.frame=GAME.frame+1
if GAME.frame<180 then if GAME.frame<180 then
if GAME.frame==179 then if GAME.frame==179 then
gameStart() gameStart()
@@ -303,6 +353,9 @@ function scene.update(dt)
elseif GAME.warnLVL>0 then elseif GAME.warnLVL>0 then
GAME.warnLVL=max(GAME.warnLVL-.026,0) GAME.warnLVL=max(GAME.warnLVL-.026,0)
end end
if GAME.warnLVL>1.126 and GAME.frame%30==0 then
SFX.fplay("warning",SETTING.sfx_warn)
end
end end
function scene.draw() function scene.draw()
@@ -378,7 +431,7 @@ function scene.draw()
end end
scene.widgetList={ scene.widgetList={
textBox, textBox,
WIDGET.newKey{name="hideChat",fText="...",x=410,y=40,w=60,font=35,code=function()hideChatBox=not hideChatBox end}, WIDGET.newKey{name="hideChat",fText="...",x=410,y=40,w=60,font=35,code=switchChat},
WIDGET.newKey{name="quit",fText="X",x=870,y=40,w=60,font=40,code=pressKey"escape"}, WIDGET.newKey{name="quit",fText="X",x=870,y=40,w=60,font=40,code=pressKey"escape"},
} }

View File

@@ -29,6 +29,30 @@ local function task_fetchRooms(task)
end end
end end
end end
local function task_createRooms(task)
local time=0
while true do
coroutine.yield()
local response,request_error=client.poll(task)
if response then
local res=json.decode(response.body)
if response.code==200 and res.message=="OK"then
LOG.print("OK")
else
LOG.print(text.httpCode..response.code..": "..res.message,"warn")
end
return
elseif request_error then
LOG.print(text.roomsCreateFailed..": "..request_error,"warn")
return
end
time=time+1
if time>210 then
LOG.print(text.roomsCreateFailed..": "..text.httpTimeout,"warn")
return
end
end
end
local function task_enterRoom(task) local function task_enterRoom(task)
local time=0 local time=0
while true do while true do
@@ -82,6 +106,19 @@ function scene.keyDown(k)
if TIME()-lastfreshTime>1 then if TIME()-lastfreshTime>1 then
fresh() fresh()
end end
elseif k=="n"then
httpRequest(
task_createRooms,
PATH.api..PATH.rooms.."/classic",
"POST",
{["Content-Type"]="application/json"},
json.encode{
email=USER.email,
access_token=USER.access_token,
room_name="Test Room "..math.random(26,626),
room_password=nil,
}
)
elseif k=="escape"then elseif k=="escape"then
SCN.back() SCN.back()
elseif rooms and #rooms>0 then elseif rooms and #rooms>0 then

View File

@@ -2,6 +2,7 @@ local gc=love.graphics
local gc_setColor,gc_circle=gc.setColor,gc.circle local gc_setColor,gc_circle=gc.setColor,gc.circle
local tc=love.touch local tc=love.touch
local int=math.floor
local max,sin=math.max,math.sin local max,sin=math.max,math.sin
local SCR=SCR local SCR=SCR
@@ -181,14 +182,23 @@ function scene.update(dt)
_=GAME.replaying _=GAME.replaying
local L=GAME.rep local L=GAME.rep
while GAME.frame==L[_]do while GAME.frame==L[_]do
local k=L[_+1] local key=L[_+1]
if k>0 then if key==0 then--Just wait
P1:pressKey(k) elseif key<=32 then--Press key
VK[k].isDown=true P1:pressKey(key)
VK[k].pressTime=10 VK[key].isDown=true
else VK[key].pressTime=10
VK[-k].isDown=false elseif key<=64 then--Release key
P1:releaseKey(-k) VK[key-32].isDown=false
P1:releaseKey(key-32)
elseif key>1023 then--Receiving garbage
local sid=key%256
local amount=int(key/256)%256
local time=int(key/4194304)%16384
local line=int(key/274877906944)%65536
local color=int(key/70368744177664)%256
P1:receive(sid,amount,time,line,color)
--TODO
end end
_=_+2 _=_+2
end end