|
1 | 1 |
|
2 | | -if not (Spring.GetConfigInt("LuaSocketEnabled", 0) == 1) then |
3 | | - --Echo("LuaSocketEnabled is disabled") |
4 | | - return false |
5 | | -end |
6 | | - |
7 | 2 | 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 | + } |
17 | 12 | end |
18 | 13 |
|
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 | | - |
33 | 14 | local url |
34 | 15 |
|
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 | | - |
101 | 16 | 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 |
115 | 17 | local parsed = url.parse(replay) |
116 | 18 | local localpath = parsed.path |
| 19 | + local replayFile = localpath:match("([^/]*)$") |
| 20 | + local restartEngine = (not WG.Chobby.Configuration:IsValidEngineVersion(engine)) and engine |
117 | 21 |
|
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) |
186 | 23 | end |
187 | 24 |
|
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 | | - |
225 | 25 | function widget:Initialize() |
226 | 26 | CHOBBY_DIR = LUA_DIRNAME .. "widgets/chobby/" |
227 | 27 | VFS.Include(LUA_DIRNAME .. "widgets/chobby/headers/exports.lua", nil, VFS.RAW_FIRST) |
|
0 commit comments