Skip to content

Commit dc7ecee

Browse files
committed
Use wrapper download to fetch replays.
1 parent cbf618e commit dc7ecee

4 files changed

Lines changed: 61 additions & 222 deletions

File tree

LuaMenu/widgets/api_download_handler.lua

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ local USE_WRAPPER_DOWNLOAD = true
3131
local typeMap = {
3232
game = "RAPID",
3333
map = "MAP",
34+
demo = "DEMO",
3435
}
3536
local reverseTypeMap = {
3637
RAPID = "game",
3738
MAP = "map",
39+
DEMO = "demo",
3840
}
3941

4042
--------------------------------------------------------------------------------
@@ -199,6 +201,20 @@ end
199201
--------------------------------------------------------------------------------
200202
-- Externals Functions
201203

204+
function externalFunctions.HasReplay(name)
205+
local replays = VFS.DirList("demos")
206+
if not (string.find(name, "demos/") or string.find(name, "demos\\")) then
207+
name = "demos/" .. name
208+
end
209+
local windowsName = name:gsub('/', '\\')
210+
for i = 1, #replays do
211+
if replays[i] == name or replays[i] == windowsName then
212+
return true
213+
end
214+
end
215+
return false
216+
end
217+
202218
function externalFunctions.QueueDownload(name, fileType, priority)
203219
priority = priority or 1
204220
if priority == -1 then

LuaMenu/widgets/gui_steam_coop_handler.lua

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ local function ResetHostData()
5757
DownloadUpdateFunction = nil
5858
end
5959

60-
local function MakeExclusivePopup(text, buttonText, ClickFunc, buttonClass, height)
60+
local function MakeExclusivePopup(text, buttonText, ClickFunc, buttonClass, width, height)
6161
if replacablePopup then
6262
replacablePopup:Close()
6363
end
64-
replacablePopup = WG.Chobby.InformationPopup(text, {caption = buttonText, closeFunc = ClickFunc, buttonClass = buttonClass, height = height})
64+
replacablePopup = WG.Chobby.InformationPopup(text, {caption = buttonText, closeFunc = ClickFunc, buttonClass = buttonClass, width = width, height = height})
6565
end
6666

6767
local function CloseExclusivePopup()
@@ -72,6 +72,14 @@ local function CloseExclusivePopup()
7272
end
7373
end
7474

75+
local function CornerEcho(title, stuff)
76+
Spring.Echo(stuff)
77+
Chotify:Post({
78+
title = title,
79+
body = stuff,
80+
})
81+
end
82+
7583
--------------------------------------------------------------------------------
7684
--------------------------------------------------------------------------------
7785
-- Top Notification
@@ -158,7 +166,7 @@ end
158166
--------------------------------------------------------------------------------
159167
-- Downloading
160168

161-
local function CheckDownloads(gameName, mapName, DoneFunc, gameList)
169+
local function CheckDownloads(gameName, mapName, DoneFunc, gameList, replayName)
162170
local haveGame = (not gameName) or WG.Package.ArchiveExists(gameName)
163171
if not haveGame then
164172
WG.DownloadHandler.MaybeDownloadArchive(gameName, "game", -1)
@@ -178,12 +186,17 @@ local function CheckDownloads(gameName, mapName, DoneFunc, gameList)
178186
end
179187
end
180188

181-
if haveGame and haveMap then
189+
local haveReplay = (not replayName) or WG.DownloadHandler.HasReplay(replayName)
190+
if not haveReplay then
191+
WG.DownloadHandler.MaybeDownloadArchive(replayName, "demo", -1)
192+
end
193+
194+
if haveGame and haveMap and haveReplay then
182195
return true
183196
end
184197

185198
local function Update()
186-
if ((not gameName) or WG.Package.ArchiveExists(gameName)) and ((not mapName) or VFS.HasArchive(mapName)) then
199+
if ((not gameName) or WG.Package.ArchiveExists(gameName)) and ((not mapName) or VFS.HasArchive(mapName)) and ((not replayName) or WG.DownloadHandler.HasReplay(replayName)) then
187200
if gameList then
188201
for i = 1, #gameList do
189202
if not WG.Package.ArchiveExists(gameList[i]) then
@@ -201,7 +214,7 @@ local function CheckDownloads(gameName, mapName, DoneFunc, gameList)
201214
end
202215
DownloadUpdateFunction = Update
203216

204-
local dlString = "Waiting on content: "
217+
local dlString = "Downloading files: "
205218
downloading = {
206219
downloads = {
207220
},
@@ -229,8 +242,14 @@ local function CheckDownloads(gameName, mapName, DoneFunc, gameList)
229242
downloading.downloads[mapName] = #downloading.progress
230243
end
231244

245+
if not haveReplay then
246+
dlString = dlString .. ("\n - " .. replayName .. ": %d%%")
247+
downloading.progress[#downloading.progress + 1] = 0
248+
downloading.downloads[replayName] = #downloading.progress
249+
end
250+
232251
downloading.dlString = dlString
233-
MakeExclusivePopup(string.format(dlString, unpack(downloading.progress)), "Cancel", CancelFunc, "negative_button", (gameList and (180 + (#gameList)*40)))
252+
MakeExclusivePopup(string.format(dlString, unpack(downloading.progress)), "Cancel", CancelFunc, "negative_button", 500, 350)
234253
end
235254

236255

@@ -343,7 +362,7 @@ end
343362
--------------------------------------------------------------------------------
344363
-- External functions: Widget <-> Widget
345364

346-
function SteamCoopHandler.AttemptGameStart(gameType, gameName, mapName, scriptTable, newFriendsReplaceAI, newReplayFile, newEngineVersion)
365+
function SteamCoopHandler.AttemptGameStart(gameType, gameName, mapName, scriptTable, newFriendsReplaceAI, newReplayFile, newEngineVersion, checkReplayDownload)
347366
if coopClient then
348367
local statusAndInvitesPanel = WG.Chobby.interfaceRoot.GetStatusAndInvitesPanel()
349368
if statusAndInvitesPanel and statusAndInvitesPanel.GetChildByName("coopPanel") then
@@ -452,7 +471,7 @@ function SteamCoopHandler.AttemptGameStart(gameType, gameName, mapName, scriptTa
452471
WG.WrapperLoopback.SteamHostGameRequest(args)
453472
end
454473

455-
if CheckDownloads(gameName, mapName, DownloadsComplete) then
474+
if CheckDownloads(gameName, mapName, DownloadsComplete, false, checkReplayDownload and newReplayFile) then
456475
DownloadsComplete()
457476
end
458477
end

LuaMenu/widgets/zk_replay_launcher.lua

Lines changed: 12 additions & 212 deletions
Original file line numberDiff line numberDiff line change
@@ -1,227 +1,27 @@
11

2-
if not (Spring.GetConfigInt("LuaSocketEnabled", 0) == 1) then
3-
--Echo("LuaSocketEnabled is disabled")
4-
return false
5-
end
6-
72
function widget:GetInfo()
8-
return {
9-
name = "ZK replay downloader",
10-
desc = "Downloads and launches ZK replays",
11-
author = "Anarchid, abma (http demo)",
12-
date = "July 2016",
13-
license = "GNU GPL, v2 or later",
14-
layer = 0,
15-
enabled = true,
16-
}
3+
return {
4+
name = "ZK replay downloader",
5+
desc = "Downloads and launches ZK replays",
6+
author = "Anarchid, abma (http demo)",
7+
date = "July 2016",
8+
license = "GNU GPL, v2 or later",
9+
layer = 0,
10+
enabled = true,
11+
}
1712
end
1813

19-
local socket = socket
20-
21-
local client
22-
local set
23-
local headersent
24-
25-
local siteName = "zero-k.info"
26-
local port = 80
27-
local path = "/replays/20160704_190323_Drab_100.sdf"
28-
local file = "20160704_190323_Drab_100.sdf"
29-
local replaydata = ""
30-
local replayMap = ""
31-
local replayGame = ""
32-
3314
local url
3415

35-
local restartEngine = false
36-
local hasFile = false
37-
38-
local function dumpConfig()
39-
-- dump all luasocket related config settings to console
40-
for _, conf in ipairs({"TCPAllowConnect", "TCPAllowListen", "UDPAllowConnect", "UDPAllowListen" }) do
41-
Spring.Echo(conf .. " = " .. Spring.GetConfigString(conf, ""))
42-
end
43-
end
44-
45-
local function newset()
46-
local reverse = {}
47-
local set = {}
48-
return setmetatable(set, {__index = {
49-
insert = function(set, value)
50-
if not reverse[value] then
51-
table.insert(set, value)
52-
reverse[value] = table.getn(set)
53-
end
54-
end,
55-
remove = function(set, value)
56-
local index = reverse[value]
57-
if index then
58-
reverse[value] = nil
59-
local top = table.remove(set)
60-
if top ~= value then
61-
reverse[top] = index
62-
set[index] = top
63-
end
64-
end
65-
end
66-
}})
67-
end
68-
69-
local function Echo(stuff)
70-
Spring.Echo(stuff)
71-
Chotify:Post({
72-
title = "Launching Replay",
73-
body = stuff,
74-
})
75-
end
76-
77-
local function Abort(reason)
78-
hasFile = false
79-
restartEngine = false
80-
81-
Chotify:Post({
82-
title = "Replay Failed",
83-
body = reason
84-
})
85-
end
86-
87-
-- initiates a connection to host:port, returns true on success
88-
local function SocketConnect(host, port)
89-
client=socket.tcp()
90-
client:settimeout(0)
91-
res, err = client:connect(host, port)
92-
if not res and not res=="timeout" then
93-
--Echo("Error in connect: "..err)
94-
return false
95-
end
96-
set = newset()
97-
set:insert(client)
98-
return true
99-
end
100-
10116
function onLaunchReplay(wtf, replay, game, map, engine)
102-
Echo("Getting data...")
103-
--Echo("url: ".. replay)
104-
--Echo("game: ".. game)
105-
--Echo('map: '.. map)
106-
--Echo('engine: '.. engine)
107-
108-
restartEngine = (not WG.Chobby.Configuration:IsValidEngineVersion(engine)) and engine
109-
hasFile = false
110-
111-
replayMap = map
112-
replayGame = game
113-
114-
-- somehow check for engine? or check if current = required, and use that
11517
local parsed = url.parse(replay)
11618
local localpath = parsed.path
19+
local replayFile = localpath:match("([^/]*)$")
20+
local restartEngine = (not WG.Chobby.Configuration:IsValidEngineVersion(engine)) and engine
11721

118-
host = parsed.host
119-
file = localpath:match("([^/]*)$")
120-
path = localpath:gsub(" ","%%20")
121-
122-
replaydata = ""
123-
124-
--Echo("Downloading replay file")
125-
SocketConnect(host, port)
126-
end
127-
128-
-- called when data was received through a connection
129-
local function SocketDataReceived(sock, str)
130-
replaydata = replaydata .. str
131-
end
132-
133-
local headersent
134-
-- called when data can be written to a socket
135-
local function SocketWriteAble(sock)
136-
if headersent==nil then
137-
-- socket is writeable
138-
headersent=1
139-
--Echo("sending http request".." GET " .. path .. " HTTP/1.0\r\nHost: " .. siteName .. " \r\n\r\n")
140-
Echo("Downloading replay file.")
141-
sock:send("GET " .. path .. " HTTP/1.0\r\nHost: " .. siteName .. " \r\n\r\n")
142-
end
143-
end
144-
145-
local function AttemptStart(saveFilename)
146-
-- Echo("Checking if ready to start")
147-
148-
if not hasFile then
149-
return -- Echo("Weird attempt to start without demofile")
150-
end
151-
152-
if not saveFilename then
153-
return
154-
end
155-
156-
Echo("Replay download complete.")
157-
WG.SteamCoopHandler.AttemptGameStart("replay", replayGame, replayMap, nil, nil, saveFilename, restartEngine)
158-
end
159-
160-
-- called when a connection is closed
161-
local function SocketClosed(sock)
162-
--Echo("closed connection")
163-
local body_start = replaydata:find("\r\n\r\n", 1, true)
164-
165-
if not body_start then
166-
Abort("Connection failure")
167-
Spring.Echo(replaydata)
168-
return
169-
end
170-
171-
body_start = body_start + 4
172-
173-
local headers = replaydata:sub(1,body_start-1)
174-
if headers:find("200 OK") then
175-
local saveFilename = 'demos/'..file
176-
local f = assert(io.open(saveFilename, 'wb')) -- open in "binary" mode
177-
f:write(replaydata:sub(body_start))
178-
f:close()
179-
replaydata = ""
180-
hasFile = true
181-
AttemptStart(saveFilename)
182-
else
183-
Abort("Unable to download replay file")
184-
Spring.Echo(headers)
185-
end
22+
WG.SteamCoopHandler.AttemptGameStart("replay", game, map, nil, nil, replayFile, restartEngine, true)
18623
end
18724

188-
function widget:Update()
189-
if set==nil or #set<=0 then
190-
return
191-
end
192-
-- get sockets ready for read
193-
local readable, writeable, err = socket.select(set, set, 0)
194-
--Spring.Utilities.TableEcho(set, "set")
195-
--Spring.Utilities.TableEcho(readable, "readable")
196-
--Spring.Utilities.TableEcho(writeable, "writeable")
197-
--Spring.Echo("headersent", headersent)
198-
--Spring.Echo("err", err)
199-
if err~=nil then
200-
-- some error happened in select
201-
if err=="timeout" then
202-
headersent = nil
203-
-- nothing to do, return
204-
return
205-
end
206-
--Echo("Error in select: " .. error)
207-
end
208-
for _, input in ipairs(readable) do
209-
local s, status, partial = input:receive('*a') --try to read all data
210-
if status == "timeout" or status == nil then
211-
SocketDataReceived(input, s or partial)
212-
elseif status == "closed" then
213-
SocketClosed(input)
214-
input:close()
215-
set:remove(input)
216-
end
217-
end
218-
219-
for __, output in ipairs(writeable) do
220-
SocketWriteAble(output)
221-
end
222-
end
223-
224-
22525
function widget:Initialize()
22626
CHOBBY_DIR = LUA_DIRNAME .. "widgets/chobby/"
22727
VFS.Include(LUA_DIRNAME .. "widgets/chobby/headers/exports.lua", nil, VFS.RAW_FIRST)

libs/liblobby/lobby/interface_skirmish.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,11 @@ function InterfaceSkirmish:StartReplay(replayFilename, myName, hostPort)
294294
IsHost=1;
295295
}
296296
]]
297-
297+
298+
if not (string.find(replayFilename, "demos/") or string.find(replayFilename, "demos\\")) then
299+
replayFilename = "demos/" .. replayFilename
300+
end
301+
298302
scriptTxt = scriptTxt:gsub("__FILE__", replayFilename)
299303
:gsub("__IP__", "127.0.0.1")
300304
:gsub("__MY_PLAYER_NAME__", myName or "(spec)")

0 commit comments

Comments
 (0)