mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 11:28:56 +00:00
Merge pull request #302 from winterheart/hog-tcp-ip
This commit is contained in:
commit
bfb3fc1980
@ -302,7 +302,7 @@ target_link_libraries(Descent3
|
||||
music networking physics renderer rtperformance sndlib ui unzip vecmat md5
|
||||
${PLATFORM_LIBS})
|
||||
target_include_directories(Descent3 PRIVATE ${PROJECT_BINARY_DIR}/lib)
|
||||
add_dependencies(Descent3 get_git_hash)
|
||||
add_dependencies(Descent3 get_git_hash Direct_TCP_IP_Hog)
|
||||
|
||||
if(UNIX)
|
||||
add_dependencies(Descent3 HogFull)
|
||||
|
@ -1,12 +1,22 @@
|
||||
set(HEADERS lanclient.h)
|
||||
set(CPPS lanclient.cpp)
|
||||
|
||||
set(NETGAME_MODULE "TCP_IP")
|
||||
add_library(Direct_TCP_IP MODULE ${CPPS})
|
||||
set_target_properties(Direct_TCP_IP PROPERTIES PREFIX "")
|
||||
set_target_properties(Direct_TCP_IP PROPERTIES OUTPUT_NAME "Direct TCP~IP")
|
||||
target_link_libraries(Direct_TCP_IP PRIVATE
|
||||
inetfile
|
||||
$<$<PLATFORM_ID:Windows>:
|
||||
ws2_32
|
||||
>
|
||||
)
|
||||
|
||||
add_library(${NETGAME_MODULE} MODULE ${CPPS} ${HEADERS})
|
||||
set_target_properties(${NETGAME_MODULE} PROPERTIES PREFIX "")
|
||||
set_target_properties(${NETGAME_MODULE} PROPERTIES SUFFIX ".d3c")
|
||||
target_link_libraries(${NETGAME_MODULE} inetfile)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
target_link_libraries(${NETGAME_MODULE} ws2_32)
|
||||
endif()
|
||||
add_custom_target(Direct_TCP_IP_Hog
|
||||
COMMAND $<TARGET_FILE:HogMaker>
|
||||
"$<TARGET_FILE_DIR:Descent3>/online/Direct TCP~IP.d3c"
|
||||
"${CMAKE_SOURCE_DIR}/netcon/lanclient/TCP_IP.d3c.txt"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/data/fullhog/"
|
||||
"$<TARGET_FILE_DIR:Direct_TCP_IP>"
|
||||
|
||||
DEPENDS Direct_TCP_IP HogMaker
|
||||
COMMENT "Generate 'Direct TCP~IP.d3c'"
|
||||
)
|
||||
|
4
netcon/lanclient/TCP_IP.d3c.txt
Normal file
4
netcon/lanclient/TCP_IP.d3c.txt
Normal file
@ -0,0 +1,4 @@
|
||||
Direct TCP~IP.so
|
||||
Direct TCP~IP.dll
|
||||
Direct TCP~IP.dylib
|
||||
lanclient.str
|
@ -62,11 +62,6 @@ set(SCRIPTS
|
||||
TrainingMission
|
||||
Y2K)
|
||||
|
||||
add_custom_target(HogFull-copy
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/scripts/data/fullhog ${CMAKE_BINARY_DIR}/scripts/data/fullhog/
|
||||
COMMENT "Copy script/data/fullhog directory"
|
||||
)
|
||||
|
||||
#add_custom_target(HogDemo-copy
|
||||
# COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/scripts/data/demohog ${CMAKE_BINARY_DIR}/scripts/data/demohog/
|
||||
# COMMENT "Copy script/data/demohog directory"
|
||||
@ -75,26 +70,11 @@ add_custom_target(HogFull-copy
|
||||
foreach(SCRIPT ${SCRIPTS})
|
||||
add_library(${SCRIPT} MODULE ${CPPS} "${SCRIPT}.cpp")
|
||||
target_link_libraries(${SCRIPT} fix)
|
||||
add_dependencies(${SCRIPT} HogFull-copy) # HogDemo-copy
|
||||
set_target_properties(${SCRIPT} PROPERTIES PREFIX "")
|
||||
if (APPLE)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set_target_properties(${SCRIPT} PROPERTIES SUFFIX ".dylib")
|
||||
endif ()
|
||||
if (UNIX)
|
||||
add_custom_command(
|
||||
TARGET ${SCRIPT}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${SCRIPT}> "${CMAKE_BINARY_DIR}/scripts/data/fullhog/"
|
||||
COMMENT "Copying file ${SCRIPT} to scripts/data/fullhog/..."
|
||||
)
|
||||
# add_custom_command(
|
||||
# TARGET ${SCRIPT}
|
||||
# POST_BUILD
|
||||
# COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${SCRIPT}> "${CMAKE_BINARY_DIR}/scripts/data/demohog/"
|
||||
# COMMENT "Copying file ${SCRIPT} to scripts/data/demohog/..."
|
||||
# )
|
||||
endif ()
|
||||
endforeach ()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(HOG_NAME "linux")
|
||||
@ -103,14 +83,20 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
endif()
|
||||
|
||||
add_custom_target(HogFull
|
||||
COMMAND $<TARGET_FILE:HogMaker> "$<TARGET_FILE_DIR:Descent3>/d3-${HOG_NAME}.hog" "${CMAKE_BINARY_DIR}/scripts/data/fullhog/d3-${HOG_NAME}-fullhog.txt"
|
||||
DEPENDS ${SCRIPTS} HogMaker data/fullhog/d3-linux-fullhog.txt data/fullhog/d3-osx-fullhog.txt
|
||||
COMMAND $<TARGET_FILE:HogMaker>
|
||||
"$<TARGET_FILE_DIR:Descent3>/d3-${HOG_NAME}.hog"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/data/fullhog/d3-${HOG_NAME}-fullhog.txt"
|
||||
"$<TARGET_FILE_DIR:AIGame>"
|
||||
DEPENDS ${SCRIPTS} HogMaker data/fullhog/d3-${HOG_NAME}-fullhog.txt
|
||||
COMMENT "Generate fullhog/d3-${HOG_NAME}.hog"
|
||||
)
|
||||
|
||||
# FIXME: there may be only one d3-linux.hog, need deal with demo somehow.
|
||||
# add_custom_target(HogLinuxDemo
|
||||
# COMMAND $<TARGET_FILE:HogMaker> "${CMAKE_BINARY_DIR}/scripts/data/demohog/d3-${HOG_NAME}.hog" "${CMAKE_BINARY_DIR}/scripts/data/demohog/d3-${HOG_NAME}-demohog.txt"
|
||||
# DEPENDS ${SCRIPTS} HogMaker
|
||||
# COMMAND $<TARGET_FILE:HogMaker>
|
||||
# "${CMAKE_BINARY_DIR}/scripts/data/demohog/d3-${HOG_NAME}.hog"
|
||||
# "${CMAKE_BINARY_DIR}/scripts/data/demohog/d3-${HOG_NAME}-demohog.txt"
|
||||
# "${CMAKE_BINARY_DIR}/scripts/"
|
||||
# DEPENDS ${SCRIPTS} HogMaker data/fullhog/d3-${HOG_NAME}-demohog.txt
|
||||
# COMMENT "Generate linuxdemohog/d3-${HOG_NAME}.hog"
|
||||
# )
|
||||
|
@ -16,15 +16,52 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "HogFormat.h"
|
||||
#include "IOOps.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
|
||||
#include "HogFormat.h"
|
||||
#include "IOOps.h"
|
||||
|
||||
namespace D3 {
|
||||
|
||||
// TODO: To our descendants from the future: remove it when code will support C++20
|
||||
template <typename TP> std::time_t to_time_t(TP tp) {
|
||||
auto sctp = std::chrono::duration_cast<std::chrono::system_clock::duration>(tp - TP::clock::now()) +
|
||||
std::chrono::system_clock::now();
|
||||
return std::chrono::system_clock::to_time_t(sctp);
|
||||
}
|
||||
|
||||
HogFileEntry::HogFileEntry(const std::filesystem::path &input) {
|
||||
m_real_path = input;
|
||||
m_flags = 0;
|
||||
m_len = (uint32_t)file_size(input);
|
||||
m_timestamp = (uint32_t)to_time_t(last_write_time(input));
|
||||
auto name = input.filename().u8string();
|
||||
std::copy(name.begin(), name.end(), m_name.begin());
|
||||
}
|
||||
|
||||
HogFileEntry::HogFileEntry(std::string name, uint32_t flags, uint32_t len, uint32_t timestamp) {
|
||||
std::copy(name.begin(), name.end(), m_name.begin());
|
||||
m_flags = flags;
|
||||
m_len = len;
|
||||
m_timestamp = timestamp;
|
||||
}
|
||||
|
||||
void HogFileEntry::SetRealPath(const std::filesystem::path &input) {
|
||||
m_real_path = input;
|
||||
m_flags = 0;
|
||||
m_len = (uint32_t)file_size(input);
|
||||
m_timestamp = (uint32_t)to_time_t(last_write_time(input));
|
||||
auto name = input.filename().u8string();
|
||||
std::copy(name.begin(), name.end(), m_name.begin());
|
||||
}
|
||||
|
||||
std::array<char, 36> char_tolower(std::array<char, 36> s) {
|
||||
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
return s;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &output, const HogHeader &header) {
|
||||
std::copy(header.tag.begin(), header.tag.end(), std::ostream_iterator<char>(output));
|
||||
bin_write(output, header.nfiles);
|
||||
@ -35,10 +72,11 @@ std::ostream &operator<<(std::ostream &output, const HogHeader &header) {
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &output, const HogFileEntry &entry) {
|
||||
std::copy(entry.name.begin(), entry.name.end(), std::ostream_iterator<char>(output));
|
||||
bin_write(output, entry.flags);
|
||||
bin_write(output, entry.len);
|
||||
bin_write(output, entry.timestamp);
|
||||
std::copy(entry.m_name.begin(), entry.m_name.end(), std::ostream_iterator<char>(output));
|
||||
bin_write(output, entry.m_flags);
|
||||
bin_write(output, entry.m_len);
|
||||
bin_write(output, entry.m_timestamp);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@ -51,4 +89,12 @@ std::ostream &operator<<(std::ostream &output, const HogFormat &format) {
|
||||
return output;
|
||||
}
|
||||
|
||||
void HogFormat::SortEntries() {
|
||||
auto customLess = [](const HogFileEntry &a, const HogFileEntry &b) {
|
||||
return (char_tolower(a.m_name) < char_tolower(b.m_name));
|
||||
};
|
||||
|
||||
std::sort(m_file_entries.begin(), m_file_entries.end(), customLess);
|
||||
}
|
||||
|
||||
} // namespace D3
|
||||
|
@ -52,11 +52,26 @@ struct HogHeader {
|
||||
std::array<char, 56> reserved = array_with(-1); // filled with 0xff
|
||||
};
|
||||
|
||||
struct HogFileEntry {
|
||||
std::array<char, 36> name = {}; // file name (36 char max)
|
||||
uint32_t flags = 0; // extra info
|
||||
uint32_t len = 0; // length of file
|
||||
uint32_t timestamp = 0; // time of file.
|
||||
class HogFileEntry {
|
||||
private:
|
||||
std::array<char, 36> m_name = {}; // file name (36 char max)
|
||||
uint32_t m_flags = 0; // extra info
|
||||
uint32_t m_len = 0; // length of file
|
||||
uint32_t m_timestamp = 0; // time of file
|
||||
std::filesystem::path m_real_path = {}; // real path
|
||||
|
||||
public:
|
||||
HogFileEntry() = default;
|
||||
explicit HogFileEntry(const std::filesystem::path &input);
|
||||
explicit HogFileEntry(std::string name, uint32_t flags = 0, uint32_t len = 0, uint32_t timestamp = 0);
|
||||
|
||||
std::filesystem::path GetRealPath() const { return m_real_path; }
|
||||
void SetRealPath(const std::filesystem::path &input);
|
||||
|
||||
std::string GetName() const { return {m_name.data()}; };
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &output, const HogFileEntry &entry);
|
||||
friend class HogFormat;
|
||||
};
|
||||
|
||||
class HogFormat {
|
||||
@ -65,12 +80,21 @@ private:
|
||||
std::vector<HogFileEntry> m_file_entries;
|
||||
|
||||
public:
|
||||
void AddEntry(HogFileEntry &entry) {
|
||||
void AddEntry(const HogFileEntry &entry) {
|
||||
m_file_entries.push_back(entry);
|
||||
m_header.nfiles++;
|
||||
m_header.file_data_offset += 48;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort entries case-insensitive alphabetically. Call this method before any
|
||||
* writing on disk: Descent 3 expects that entries in HOG are sorted.
|
||||
*/
|
||||
void SortEntries();
|
||||
|
||||
uint32_t Count() const { return m_header.nfiles; }
|
||||
std::vector<HogFileEntry> GetEntries() const { return m_file_entries; }
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &output, const HogFormat &format);
|
||||
};
|
||||
|
||||
|
@ -32,41 +32,58 @@ template <typename TP> std::time_t to_time_t(TP tp) {
|
||||
return std::chrono::system_clock::to_time_t(sctp);
|
||||
}
|
||||
|
||||
std::string str_tolower(std::string s) {
|
||||
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
return s;
|
||||
// Find requested file in search paths
|
||||
std::filesystem::path resolve_path(const std::vector<std::filesystem::path> &search_path,
|
||||
const std::filesystem::path &file) {
|
||||
for (const auto &i : search_path) {
|
||||
if (is_regular_file((i / file))) {
|
||||
return (i / file);
|
||||
}
|
||||
}
|
||||
// Return empty path
|
||||
return std::filesystem::path{};
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::vector<std::filesystem::path> input_files;
|
||||
|
||||
if (argc != 3) {
|
||||
if (argc < 3) {
|
||||
std::cout << "HogMaker v" << D3_MAJORVER << "." << D3_MINORVER << "." << D3_BUILD << "-g" << D3_GIT_HASH << "\n"
|
||||
<< "Usage:\n"
|
||||
<< " " << argv[0] << " <hogfile.hog> <inputfile.txt>\n"
|
||||
<< " " << argv[0] << " <hogfile.hog> <inputfile.txt> [search_path]\n"
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::filesystem::path hog_filename{argv[1]};
|
||||
std::filesystem::path input_filename{argv[2]};
|
||||
// Default search path
|
||||
std::vector<std::filesystem::path> search_paths{input_filename.parent_path()};
|
||||
// Additional search paths
|
||||
for (int i = 3; i < argc; i++) {
|
||||
if (is_directory(std::filesystem::path(argv[i]))) {
|
||||
search_paths.emplace_back(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_regular_file(input_filename)) {
|
||||
std::cout << input_filename << " is not a regular file!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
D3::HogFormat hog_table;
|
||||
|
||||
try {
|
||||
create_directories(absolute(hog_filename).parent_path());
|
||||
std::ifstream input(input_filename, std::ios_base::in);
|
||||
auto parent_input_path = input_filename.parent_path();
|
||||
for (std::string line; std::getline(input, line);) {
|
||||
if (!is_regular_file(parent_input_path / line)) {
|
||||
std::cout << "Warning! File " << line << " from " << input_filename << " does not exist! Skipping..."
|
||||
<< std::endl;
|
||||
} else if (std::filesystem::path(line).filename().string().size() > 36) {
|
||||
auto resolved_file = resolve_path(search_paths, line);
|
||||
if (resolved_file.empty()) {
|
||||
std::cout << "Warning! File " << line << " from " << input_filename << " not found! Skipping..." << std::endl;
|
||||
} else if (line.size() > 36) {
|
||||
std::cout << "Warning! Length of name of file " << line << " is more than 36 symbols! Skipping..." << std::endl;
|
||||
} else {
|
||||
input_files.emplace_back(parent_input_path / line);
|
||||
hog_table.AddEntry(D3::HogFileEntry(resolved_file));
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,39 +92,16 @@ int main(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto customLess = [](const std::filesystem::path &a, const std::filesystem::path &b) {
|
||||
return (str_tolower(a.u8string()) < str_tolower(b.u8string()));
|
||||
};
|
||||
hog_table.SortEntries();
|
||||
|
||||
std::sort(input_files.begin(), input_files.end(), customLess);
|
||||
|
||||
D3::HogFormat hog_table;
|
||||
|
||||
for (const auto &i : input_files) {
|
||||
try {
|
||||
D3::HogFileEntry entry;
|
||||
auto name = i.filename().u8string();
|
||||
std::copy(name.begin(), name.end(), entry.name.begin());
|
||||
entry.flags = 0;
|
||||
entry.len = (uint32_t)file_size(i);
|
||||
entry.timestamp = (uint32_t)to_time_t(last_write_time(i));
|
||||
|
||||
hog_table.AddEntry(entry);
|
||||
|
||||
} catch (std::exception &e) {
|
||||
std::cout << "Exception: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Creating " << hog_filename << "..." << std::endl;
|
||||
std::cout << "Creating " << absolute(hog_filename) << "..." << std::endl;
|
||||
std::fstream ofs(hog_filename, std::ios_base::out | std::ios_base::binary);
|
||||
|
||||
ofs << hog_table;
|
||||
for (const auto &i : input_files) {
|
||||
std::cout << "Adding " << i << "... ";
|
||||
for (const auto& i : hog_table.GetEntries()) {
|
||||
std::cout << "Adding " << i.GetName() << "... ";
|
||||
try {
|
||||
std::fstream ifs(i, std::ios_base::in | std::ios_base::binary);
|
||||
std::fstream ifs(i.GetRealPath(), std::ios_base::in | std::ios_base::binary);
|
||||
std::copy((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>(),
|
||||
std::ostreambuf_iterator<char>(ofs));
|
||||
} catch (std::exception &e) {
|
||||
|
Loading…
Reference in New Issue
Block a user