summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 7ddf228)
raw | patch | inline | side by side (parent: 7ddf228)
author | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Sun, 13 Oct 2019 00:21:57 +0000 (03:21 +0300) | ||
committer | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Sun, 13 Oct 2019 00:22:55 +0000 (03:22 +0300) |
src/game/g_game.pas | patch | blob | history | |
src/game/g_map.pas | patch | blob | history | |
src/game/g_net.pas | patch | blob | history | |
src/game/g_res_downloader.pas | patch | blob | history |
diff --git a/src/game/g_game.pas b/src/game/g_game.pas
index 317f0c419c362a9d9ee4fa90e246afc6e0a8f49b..4e2382628b74a8faa5a2198439b96e5695ae8bc8 100644 (file)
--- a/src/game/g_game.pas
+++ b/src/game/g_game.pas
end
else
begin
- gWADHash := MD5File(nws);
+ if (g_Game_IsNet) then gWADHash := MD5File(nws);
//writeln('********: nws=', nws, ' : Map=', Map, ' : nw=', NewWAD, ' : resname=', ResName);
g_Game_LoadWAD(NewWAD);
end;
diff --git a/src/game/g_map.pas b/src/game/g_map.pas
index 392d45b328918d865718815ad1daff07c0889db1..60aefbda87e3e205fc952aa4b142fbb2cb763d02 100644 (file)
--- a/src/game/g_map.pas
+++ b/src/game/g_map.pas
gLiftMap: array of array of DWORD;
gWADHash: TMD5Digest;
BackID: DWORD = DWORD(-1);
- gExternalResources: TStringList;
+ gExternalResources: array of TDiskFileInfo = nil;
gMovingWallIds: array of Integer = nil;
gdbg_map_use_accel_render: Boolean = true;
Result := '';
end;
-procedure addResToExternalResList(res: string);
+
+procedure addResToExternalResList (res: AnsiString);
+var
+ uname: AnsiString;
+ f: Integer;
+ fi: TDiskFileInfo;
begin
- //e_LogWritefln('DBG: ***trying external resource %s', [res]);
- res := toLowerCase1251(extractWadName(res));
- // ignore "standart.wad"
- if (res <> '') {and (res <> 'standart.wad')} and (gExternalResources.IndexOf(res) = -1) then
+ if g_Game_IsClient or not g_Game_IsNet then exit;
+ if (length(res) = 0) then exit; // map wad
+ res := extractWadName(res);
+ if (length(res) = 0) then exit; // map wad
+ uname := toLowerCase1251(res);
+ // do not add duplicates
+ for f := 0 to High(gExternalResources) do
begin
- //e_LogWritefln('DBG: added external resource %s', [res]);
- gExternalResources.Add(res);
+ if (gExternalResources[f].userName = uname) then exit;
end;
-end;
-
-procedure generateExternalResourcesList({mapReader: TMapReader_1}map: TDynRecord);
-//var
- //textures: TTexturesRec1Array;
- //textures: TDynField;
- //trec: TDynRecord;
- //mapHeader: TMapHeaderRec_1;
- //i: integer;
- //resFile: String = '';
-begin
- if gExternalResources = nil then
- gExternalResources := TStringList.Create;
-
- gExternalResources.Clear;
-
- (*
- {
- textures := GetTextures(map);
- for i := 0 to High(textures) do
+ // add new resource
+ fi.userName := uname;
+ if (not GetDiskFileInfo(GameDir+'/wads/'+res, fi)) then
+ begin
+ fi.tag := -1;
+ end
+ else
begin
- addResToExternalResList(resFile);
+ fi.tag := 0; // non-zero means "cannot caclucate hash"
+ try
+ fi.hash := MD5File(fi.diskName);
+ except
+ fi.tag := -1;
+ end;
end;
- }
+ //e_LogWritefln('addext: res=[%s]; uname=[%s]; diskName=[%s]', [res, fi.userName, fi.diskName]);
+ SetLength(gExternalResources, length(gExternalResources)+1);
+ gExternalResources[High(gExternalResources)] := fi;
+end;
+
- textures := map['texture'];
- if (textures <> nil) then
+procedure compactExtResList ();
+var
+ src, dest: Integer;
+begin
+ src := 0;
+ dest := 0;
+ for src := 0 to High(gExternalResources) do
begin
- for trec in textures do
+ if (gExternalResources[src].tag = 0) then
begin
- addResToExternalResList(resFile);
+ // copy it
+ if (dest <> src) then gExternalResources[dest] := gExternalResources[src];
+ Inc(dest);
end;
end;
+ if (dest <> length(gExternalResources)) then SetLength(gExternalResources, dest);
+end;
- textures := nil;
- *)
-
- //mapHeader := GetMapHeader(map);
+procedure generateExternalResourcesList (map: TDynRecord);
+begin
+ SetLength(gExternalResources, 0);
addResToExternalResList(map.MusicName);
addResToExternalResList(map.SkyName);
end;
end;
end;
+ compactExtResList();
e_WriteLog('Done loading map.', TMsgType.Notify);
Result := True;
end;
diff --git a/src/game/g_net.pas b/src/game/g_net.pas
index d3e67cfd6ef34c4ad3fdfc9cc0ed8ab1c1f6b2f4..391e09c520a6f6513ecfe6c52a9377c2009a4bc8 100644 (file)
--- a/src/game/g_net.pas
+++ b/src/game/g_net.pas
{$ENDIF}
type
+ TNetMapResourceInfo = record
+ wadName: AnsiString; // wad file name, without a path
+ size: Integer; // wad file size (-1: size and hash are not known)
+ hash: TMD5Digest; // wad hash
+ end;
+
+ TNetMapResourceInfoArray = array of TNetMapResourceInfo;
+
TNetFileTransfer = record
diskName: string;
hash: TMD5Digest;
function g_Net_UserRequestExit: Boolean;
-function g_Net_Wait_MapInfo (var tf: TNetFileTransfer; resList: TStringList): Integer;
+function g_Net_Wait_MapInfo (var tf: TNetFileTransfer; var resList: TNetMapResourceInfoArray): Integer;
function g_Net_RequestResFileInfo (resIndex: LongInt; out tf: TNetFileTransfer): Integer;
function g_Net_AbortResTransfer (var tf: TNetFileTransfer): Boolean;
function g_Net_ReceiveResourceFile (resIndex: LongInt; var tf: TNetFileTransfer; strm: TStream): Integer;
ridx: Integer;
dfn: AnsiString;
md5: TMD5Digest;
- st: TStream;
+ //st: TStream;
size: LongInt;
+ fi: TDiskFileInfo;
begin
// find client index by peer
for f := Low(NetClients) to High(NetClients) do
end;
// get resource index
ridx := msg.ReadLongInt();
- if (ridx < -1) or (ridx >= gExternalResources.Count) then
+ if (ridx < -1) or (ridx >= length(gExternalResources)) then
begin
e_LogWritefln('Invalid resource index %d', [ridx], TMsgType.Warning);
killClientByFT(nc^);
exit;
end;
- if (ridx < 0) then fname := MapsDir+gGameSettings.WAD else fname := GameDir+'/wads/'+gExternalResources[ridx];
+ if (ridx < 0) then fname := MapsDir+gGameSettings.WAD else fname := {GameDir+'/wads/'+}gExternalResources[ridx].diskName;
if (length(fname) = 0) then
begin
e_WriteLog('Invalid filename: '+fname, TMsgType.Warning);
exit;
end;
// calculate hash
- //TODO: cache hashes
- tf.hash := MD5File(tf.diskName);
+ //tf.hash := MD5File(tf.diskName);
+ if (ridx < 0) then tf.hash := gWADHash else tf.hash := gExternalResources[ridx].hash;
// create file stream
tf.diskName := findDiskWad(fname);
try
trans_omsg.Clear();
dfn := findDiskWad(MapsDir+gGameSettings.WAD);
if (dfn = '') then dfn := '!wad_not_found!.wad'; //FIXME
- md5 := MD5File(dfn);
+ //md5 := MD5File(dfn);
+ md5 := gWADHash;
+ if (not GetDiskFileInfo(dfn, fi)) then
+ begin
+ e_LogWritefln('client #%d requested map info, but i cannot get file info', [nc.ID]);
+ killClientByFT(nc^);
+ exit;
+ end;
+ size := fi.size;
+ {
st := openDiskFileRO(dfn);
if not assigned(st) then exit; //wtf?!
size := st.size;
st.Free;
+ }
// packet type
trans_omsg.Write(Byte(NTF_SERVER_MAP_INFO));
// map wad name
// map wad size
trans_omsg.Write(size);
// number of external resources for map
- trans_omsg.Write(LongInt(gExternalResources.Count));
+ trans_omsg.Write(LongInt(length(gExternalResources)));
// external resource names
- for f := 0 to gExternalResources.Count-1 do
+ for f := 0 to High(gExternalResources) do
begin
- trans_omsg.Write(ExtractFileName(gExternalResources[f])); // GameDir+'/wads/'+ResList.Strings[i]
+ // old style packet
+ //trans_omsg.Write(ExtractFileName(gExternalResources[f])); // GameDir+'/wads/'+ResList.Strings[i]
+ // new style packet
+ trans_omsg.Write('!');
+ trans_omsg.Write(LongInt(gExternalResources[f].size));
+ trans_omsg.Write(gExternalResources[f].hash);
+ trans_omsg.Write(ExtractFileName(gExternalResources[f].diskName));
end;
// send packet
if not ftransSendServerMsg(nc^, trans_omsg) then exit;
//
// returns `false` on error or user abort
// fills:
-// hash
-// size
-// chunkSize
+// diskName: map wad file name (without a path)
+// hash: map wad hash
+// size: map wad size
+// chunkSize: set too
+// resList: list of resource wads
// returns:
// <0 on error
// 0 on success
// 1 on user abort
// 2 on server abort
// for maps, first `tf.diskName` name will be map wad name, and `tf.hash`/`tf.size` will contain map info
-function g_Net_Wait_MapInfo (var tf: TNetFileTransfer; resList: TStringList): Integer;
+function g_Net_Wait_MapInfo (var tf: TNetFileTransfer; var resList: TNetMapResourceInfoArray): Integer;
var
ev: ENetEvent;
rMsgId: Byte;
status: cint;
s: AnsiString;
rc, f: LongInt;
+ ri: ^TNetMapResourceInfo;
begin
+ SetLength(resList, 0);
+
// send request
trans_omsg.Clear();
trans_omsg.Write(Byte(NTF_CLIENT_MAP_REQUEST));
e_LogWritefln('g_Net_Wait_MapInfo: creating map info packet...', []);
if not msg.Init(ev.packet^.data+1, ev.packet^.dataLength-1, True) then exit;
e_LogWritefln('g_Net_Wait_MapInfo: parsing map info packet (rd=%d; max=%d)...', [msg.ReadCount, msg.MaxSize]);
- resList.Clear();
+ SetLength(resList, 0); // just in case
// map wad name
tf.diskName := msg.ReadString();
e_LogWritefln('g_Net_Wait_MapInfo: map wad is `%s`', [tf.diskName]);
exit;
end;
e_LogWritefln('g_Net_Wait_MapInfo: map external resource count is %d', [rc]);
+ SetLength(resList, rc);
// external resource names
for f := 0 to rc-1 do
begin
- s := ExtractFileName(msg.ReadString());
- if (length(s) = 0) then
+ ri := @resList[f];
+ s := msg.ReadString();
+ if (length(s) = 0) then begin result := -1; exit; end;
+ if (s = '!') then
+ begin
+ // extended packet
+ ri.size := msg.ReadLongInt();
+ ri.hash := msg.ReadMD5();
+ ri.wadName := ExtractFileName(msg.ReadString());
+ if (length(ri.wadName) = 0) or (ri.size < 0) then begin result := -1; exit; end;
+ end
+ else
begin
- Result := -1;
- exit;
+ // old-style packet, only name
+ ri.wadName := ExtractFileName(s);
+ if (length(ri.wadName) = 0) then begin result := -1; exit; end;
+ ri.size := -1; // unknown
end;
- resList.append(s);
end;
e_LogWritefln('g_Net_Wait_MapInfo: got map info', []);
Result := 0; // success
index 68ceb0a71aa8be99baf763cbf8d98ba5b8ad366c..438cd58357c6a1a0ecde23a83ffe62f4cc12c2ed 100644 (file)
end;
-//==========================================================================
-//
-// scanDir
-//
-// look for a wad to match the hash
-// scans subdirs, ignores known wad extensions
-//
-// returns found wad disk name, or empty string
-//
-//==========================================================================
-(*
-function scanDir (dirName: AnsiString; baseName: AnsiString; const resMd5: TMD5Digest): AnsiString;
-var
- searchResult: TSearchRec;
- dfn: AnsiString;
- md5: TMD5Digest;
- dirs: array of AnsiString;
- f: Integer;
-begin
- result := '';
- SetLength(dirs, 0);
- if (length(baseName) = 0) then exit;
- dirName := IncludeTrailingPathDelimiter(dirName);
- e_LogWritefln('scanning dir `%s` for file `%s`...', [dirName, baseName]);
-
- // scan files
- if (FindFirst(dirName+'*', faAnyFile, searchResult) <> 0) then exit;
- try
- repeat
- if ((searchResult.Attr and faDirectory) = 0) then
- begin
- if (isWadNamesEqu(searchResult.Name, baseName)) then
- begin
- dfn := dirName+searchResult.Name;
- if FileExists(dfn) then
- begin
- e_LogWritefln(' found `%s`...', [dfn]);
- md5 := MD5File(dfn);
- if MD5Match(md5, resMd5) then
- begin
- e_LogWritefln(' MATCH `%s`...', [dfn]);
- SetLength(dirs, 0);
- result := dfn;
- exit;
- end;
- end;
- end;
- end
- else
- begin
- if (searchResult.Name <> '.') and (searchResult.Name <> '..') then
- begin
- dfn := dirName+searchResult.Name;
- SetLength(dirs, Length(dirs)+1);
- dirs[length(dirs)-1] := dfn;
- end;
- end;
- until (FindNext(searchResult) <> 0);
- finally
- FindClose(searchResult);
- end;
-
- // scan subdirs
- for f := 0 to High(dirs) do
- begin
- dfn := dirs[f];
- result := scanDir(dfn, baseName, resMd5);
- if (length(result) <> 0) then begin SetLength(dirs, 0); exit; end;
- end;
- SetLength(dirs, 0);
-end;
-*)
-
-
//==========================================================================
//
// findExistingMapWadWithHash
function g_Res_DownloadMapWAD (FileName: AnsiString; const mapHash: TMD5Digest): AnsiString;
var
tf: TNetFileTransfer;
- resList: TStringList;
+ resList: array of TNetMapResourceInfo = nil;
f, res: Integer;
strm: TStream;
fname: AnsiString;
md5: TMD5Digest;
mapdbUpdated: Boolean = false;
resdbUpdated: Boolean = false;
+ transStarted: Boolean;
begin
result := '';
clearReplacementWads();
- resList := TStringList.Create();
-
try
g_Res_received_map_start := 1;
g_Console_Add(Format(_lc[I_NET_MAP_DL], [FileName]));
end;
// download resources
- for f := 0 to resList.Count-1 do
+ for f := 0 to High(resList) do
begin
- res := g_Net_RequestResFileInfo(f, tf);
- if (res <> 0) then begin result := ''; exit; end;
+ // if we got a new-style reslist packet, use received data to check for resource files
+ if (resList[f].size < 0) then
+ begin
+ // old-style packet
+ transStarted := true;
+ res := g_Net_RequestResFileInfo(f, tf);
+ if (res <> 0) then begin result := ''; exit; end;
+ end
+ else
+ begin
+ // new-style packet
+ transStarted := false;
+ tf.diskName := resList[f].wadName;
+ tf.hash := resList[f].hash;
+ tf.size := resList[f].size;
+ end;
if (isIgnoredResWad(tf.diskName)) then
begin
// ignored file, abort download
- g_Net_AbortResTransfer(tf);
+ if (transStarted) then g_Net_AbortResTransfer(tf);
e_LogWritefln('ignoring wad resource `%s` by user request', [tf.diskName]);
continue;
end;
if (length(wadname) <> 0) then
begin
// already here
- g_Net_AbortResTransfer(tf);
+ if (transStarted) then g_Net_AbortResTransfer(tf);
addReplacementWad(tf.diskName, wadname);
end
else
begin
+ if (not transStarted) then
+ begin
+ res := g_Net_RequestResFileInfo(f, tf);
+ if (res <> 0) then begin result := ''; exit; end;
+ end;
try
CreateDir(GameDir+'/wads/downloads');
except
end;
end;
finally
- resList.Free;
+ SetLength(resList, 0);
g_Res_received_map_start := 0;
end;