Skip to content

Commit 5ce5edc

Browse files
committed
Downloads handled by bridge instead of mod
The bridge will be what handles downloading the mods instead of relying on the mod-side to write the files itself. The bridge communicates the progress of the file, however. Also introduces a basic state sharing framework but at the moment is used to share where mods should be downloaded to and a to-be-implemented switch to enable unix compatibility should the bridge not need to fix the given path download path. State is initially given by the mod on connect.
1 parent 67ae4e3 commit 5ce5edc

6 files changed

Lines changed: 347 additions & 150 deletions

File tree

KISSMultiplayer/lua/ge/extensions/kissmods.lua

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,18 +107,13 @@ local function set_mods_list(mod_list)
107107
end
108108
end
109109

110-
local function open_file(name)
111-
if not string.endswith(name, ".zip") then return end
110+
local function get_mod_directory()
112111
if not FS:directoryExists("/kissmp_mods/") then
113112
FS:directoryCreate("/kissmp_mods/")
114113
end
115-
local path = "/kissmp_mods/"..name
116-
print(path)
117-
local file = io.open(path, "wb")
118-
return file
114+
return FS:getFileRealPath("/kissmp_mods/")
119115
end
120116

121-
M.open_file = open_file
122117
M.check_mods = check_mods
123118
M.is_special_mod = is_special_mod
124119
M.mount_mod = mount_mod
@@ -127,5 +122,6 @@ M.deactivate_all_mods = deactivate_all_mods
127122
M.set_mods_list = set_mods_list
128123
M.update_status_all = update_status_all
129124
M.update_status = update_status
125+
M.get_mod_directory = get_mod_directory
130126

131127
return M

KISSMultiplayer/lua/ge/extensions/network.lua

Lines changed: 65 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ local M = {}
22

33
M.VERSION_STR = "0.4.5"
44

5-
M.downloads = {}
6-
M.downloading = false
75
M.downloads_status = {}
86

97
local current_download = nil
@@ -12,6 +10,13 @@ local socket = require("socket")
1210
local messagepack = require("lua/common/libs/Lua-MessagePack/MessagePack")
1311
local ping_send_time = 0
1412

13+
-- shared::State
14+
-- Should be in it's own module, but for now this is fine.
15+
local state = {
16+
download_directory = kissmods.get_mod_directory(),
17+
disregard_unix_path_correction = false
18+
}
19+
1520
M.players = {}
1621
M.socket = socket
1722
M.base_secret = "None"
@@ -75,27 +80,6 @@ local function disconnect(data)
7580
returnToMainMenu()
7681
end
7782

78-
local function handle_disconnected(data)
79-
disconnect(data)
80-
end
81-
82-
local function handle_file_transfer(data)
83-
kissui.show_download = true
84-
local file_len = ffi.cast("uint32_t*", ffi.new("char[?]", 5, data:sub(1, 4)))[0]
85-
local file_name = data:sub(5, #data)
86-
local chunks = math.floor(file_len / FILE_TRANSFER_CHUNK_SIZE)
87-
88-
current_download = {
89-
file_len = file_len,
90-
file_name = file_name,
91-
chunks = chunks,
92-
last_chunk = file_len - chunks * FILE_TRANSFER_CHUNK_SIZE,
93-
current_chunk = 0,
94-
file = kissmods.open_file(file_name)
95-
}
96-
M.downloading = true
97-
end
98-
9983
local function handle_player_info(player_info)
10084
M.players[player_info.id] = player_info
10185
end
@@ -147,6 +131,45 @@ local function handle_chat(data)
147131
kissui.chat.add_message(data[1], nil, data[2])
148132
end
149133

134+
local function change_map(map)
135+
if FS:fileExists(map) or FS:directoryExists(map) then
136+
vehiclemanager.loading_map = true
137+
freeroam_freeroam.startFreeroam(map)
138+
else
139+
kissui.chat.add_message("Map file doesn't exist. Check if mod containing map is enabled", kissui.COLOR_RED)
140+
disconnect()
141+
end
142+
end
143+
144+
local function on_finished_download()
145+
vehiclemanager.loading_map = true
146+
M.downloads_status = {}
147+
change_map(M.connection.server_info.map)
148+
end
149+
150+
local function on_download_progress(data)
151+
local name, recieved, total = data[1], data[2], data[3]
152+
kissui.show_download = true
153+
154+
M.downloads_status[name] = {
155+
name = name,
156+
progress = recieved/total
157+
}
158+
if recieved >= total then
159+
M.downloads_status[name] = nil
160+
M.connection.mods_left = M.connection.mods_left - 1
161+
kissmods.mount_mod(name)
162+
end
163+
if M.connection.mods_left <= 0 then
164+
kissui.show_download = false
165+
on_finished_download()
166+
end
167+
end
168+
169+
local function on_state_update(data)
170+
print("Updating the mod's state is not implemented yet!")
171+
end
172+
150173
local function onExtensionLoaded()
151174
message_handlers.VehicleUpdate = vehiclemanager.update_vehicle
152175
message_handlers.VehicleSpawn = vehiclemanager.spawn_vehicle
@@ -162,9 +185,11 @@ local function onExtensionLoaded()
162185
message_handlers.CouplerAttached = vehiclemanager.attach_coupler
163186
message_handlers.CouplerDetached = vehiclemanager.detach_coupler
164187
message_handlers.ElectricsUndefinedUpdate = vehiclemanager.electrics_diff_update
188+
message_handlers.DownloadProgress = on_download_progress
189+
message_handlers.StateUpdate = on_state_update
165190
end
166191

167-
local function send_data(raw_data, reliable)
192+
local function send_data_no_connection_check(raw_data, reliable)
168193
if type(raw_data) == "number" then
169194
print("NOT IMPLEMENTED. PLEASE REPORT TO KISSMP DEVELOPERS. CODE: "..raw_data)
170195
return
@@ -176,7 +201,6 @@ local function send_data(raw_data, reliable)
176201
else
177202
data = jsonEncode(raw_data)
178203
end
179-
if not M.connection.connected then return -1 end
180204
local len = #data
181205
local len = ffi.string(ffi.new("uint32_t[?]", 1, {len}), 4)
182206
if reliable then
@@ -188,6 +212,11 @@ local function send_data(raw_data, reliable)
188212
M.connection.tcp:send(data)
189213
end
190214

215+
local function send_data(raw_data, reliable)
216+
if not M.connection.connected then return -1 end
217+
send_data_no_connection_check(raw_data, reliable)
218+
end
219+
191220
local function sanitize_addr(addr)
192221
-- Trim leading and trailing spaces that might occur during a copy/paste
193222
local sanitized = addr:gsub("^%s*(.-)%s*$", "%1")
@@ -204,20 +233,11 @@ local function generate_secret(server_identifier)
204233
return hashStringSHA1(secret)
205234
end
206235

207-
local function change_map(map)
208-
if FS:fileExists(map) or FS:directoryExists(map) then
209-
vehiclemanager.loading_map = true
210-
freeroam_freeroam.startFreeroam(map)
211-
else
212-
kissui.chat.add_message("Map file doesn't exist. Check if mod containing map is enabled", kissui.COLOR_RED)
213-
disconnect()
214-
end
215-
end
216-
217236
local function connect(addr, player_name)
218237
if M.connection.connected then
219238
disconnect()
220239
end
240+
M.downloads_status = {}
221241
M.players = {}
222242

223243
print("Connecting...")
@@ -228,10 +248,16 @@ local function connect(addr, player_name)
228248
local connected, err = M.connection.tcp:connect("127.0.0.1", "7894")
229249

230250
-- Send server address to the bridge
231-
local addr_lenght = ffi.string(ffi.new("uint32_t[?]", 1, {#addr}), 4)
232-
M.connection.tcp:send(addr_lenght)
251+
local addr_length = ffi.string(ffi.new("uint32_t[?]", 1, {#addr}), 4)
252+
M.connection.tcp:send(addr_length)
233253
M.connection.tcp:send(addr)
234254

255+
-- Send the initial state
256+
kissui.chat.add_message("Sending state...")
257+
send_data_no_connection_check({
258+
StateUpdate = state
259+
}, true)
260+
235261
local connection_confirmed = M.connection.tcp:receive(1)
236262
if connection_confirmed then
237263
if connection_confirmed ~= string.char(1) then
@@ -320,11 +346,6 @@ local function send_messagepack(data_type, reliable, data)
320346
send_data(data_type, reliable, data)
321347
end
322348

323-
local function on_finished_download()
324-
vehiclemanager.loading_map = true
325-
change_map(M.connection.server_info.map)
326-
end
327-
328349
local function send_ping()
329350
ping_send_time = socket.gettime()
330351
send_data(
@@ -340,9 +361,7 @@ local function cancel_download()
340361
io.close(current_download.file)
341362
current_download = nil
342363
M.downloading = false]]--
343-
for k, v in pairs(M.downloads) do
344-
M.downloads[k]:close()
345-
end
364+
M.downloads_status = {}
346365
end
347366

348367
local function onUpdate(dt)
@@ -372,41 +391,7 @@ local function onUpdate(dt)
372391
end
373392
end
374393
elseif string.byte(msg_type) == 0 then -- Binary data
375-
M.downloading = true
376-
kissui.show_download = true
377-
local name_b = M.connection.tcp:receive(4)
378-
local len_n = ffi.cast("uint32_t*", ffi.new("char[?]", 5, name_b))
379-
local name, _, _ = M.connection.tcp:receive(len_n[0])
380-
local chunk_n_b = M.connection.tcp:receive(4)
381-
local chunk_a_b = M.connection.tcp:receive(4)
382-
local read_size_b = M.connection.tcp:receive(4)
383-
local chunk_n = ffi.cast("uint32_t*", ffi.new("char[?]", 5, chunk_n_b))[0]
384-
local file_length = ffi.cast("uint32_t*", ffi.new("char[?]", 5, chunk_a_b))[0]
385-
local read_size = ffi.cast("uint32_t*", ffi.new("char[?]", 5, read_size_b))[0]
386-
local file_data, _, _ = M.connection.tcp:receive(read_size)
387-
M.downloads_status[name] = {
388-
name = name,
389-
progress = 0
390-
}
391-
M.downloads_status[name].progress = chunk_n * FILE_TRANSFER_CHUNK_SIZE / file_length
392-
local file = M.downloads[name]
393-
if not file then
394-
M.downloads[name] = kissmods.open_file(name)
395-
end
396-
M.downloads[name]:write(file_data)
397-
if read_size < FILE_TRANSFER_CHUNK_SIZE then
398-
M.downloading = false
399-
kissui.show_download = false
400-
kissmods.mount_mod(name)
401-
M.downloads[name]:close()
402-
M.downloads[name] = nil
403-
M.downloads_status = {}
404-
M.connection.mods_left = M.connection.mods_left - 1
405-
end
406-
if M.connection.mods_left <= 0 then
407-
on_finished_download()
408-
end
409-
M.connection.tcp:settimeout(0.0)
394+
-- BINARY DOWNLOADS DEPRECATED
410395
break
411396
elseif string.byte(msg_type) == 2 then
412397
local len_b = M.connection.tcp:receive(4)

kissmp-bridge/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ rodio = "0.14"
3131
cpal = "0.13"
3232
fon = "0.5.0"
3333
log = "0.4"
34-
indoc = "1.0"
34+
indoc = "1.0"
35+
dirs = "4.0.0"

0 commit comments

Comments
 (0)