Merge pull request #302 from winterheart/hog-tcp-ip

This commit is contained in:
Jeod 2024-05-08 14:21:13 -04:00 committed by GitHub
commit bfb3fc1980
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 153 additions and 89 deletions

View File

@ -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)

View File

@ -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'"
)

View File

@ -0,0 +1,4 @@
Direct TCP~IP.so
Direct TCP~IP.dll
Direct TCP~IP.dylib
lanclient.str

View File

@ -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"
# )

View File

@ -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

View File

@ -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);
};

View File

@ -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) {