Skip to content

Commit

Permalink
Merge pull request #91 from OutpostUniverse/AddNewModuleTests
Browse files Browse the repository at this point in the history
Add new module tests
  • Loading branch information
Brett208 committed May 4, 2019
2 parents 56e4471 + 94deed5 commit 8962314
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 20 deletions.
17 changes: 6 additions & 11 deletions ReadMe.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ op2ext provides the following extensions for Outpost 2:
- Allows saving previously used IP address in a drop-down menu for easy selection when joining repeat matches.

* Unified message logging

Writing Custom Modules
------------------------------------------
op2ext.dll is included in releases of Outpost 2 on Outpost Universe. This DLL allow integration of separately compiled modules into any copy of Outpost 2. Custom modules must be designed to hook into op2ext.dll through functions that export using the C Application Binary Interface (ABI). Modules may also consist of simply overwriting game assets without additional programming.
Expand All @@ -49,16 +49,10 @@ Each new module for Outpost 2 should be placed in a separate directory that resi

The two types of modules, console and .ini modules, use different function hooks to pass data into op2ext. They both have access to the same set of op2ext exported functions. To gain access to op2ext's exported functions, include op2ext.h in your project. Detailed usage instructions for the functions are contained in op2ext.h.

- size_t GetGameDir_s(char* buffer, size_t bufferSize)
- size_t GetConsoleModDir_s(char* buffer, size_t bufferSize)
- void AddVolToList(const char* volName)
- void SetSerialNumber(char major, char minor, char revision)
- void Log(const char* message)
- [DEPRECATED] void GetGameDir(char* buffer)
- [DEPRECATED] char* GetCurrentModDir(); - Returns the directory of the console loaded module only (if one exists)

Custom modules are encouraged to use the Log function to log useful information for troubleshooting various failures or degraded states. op2ext itself uses the logger as well. The log file will be named Outpost2Log.txt and will be created in the same directory as Outpost2.exe.


Module names are case insensitive. You can check if a module is loaded using functions declared in op2ext.h.

Console Modules
------------------------------------------
If the module needs to redirect where Outpost 2 looks for standard game resources without using a custom DLL and/or should not always be included with Outpost 2, consider making it a console module.
Expand All @@ -72,7 +66,7 @@ Game resources that may be redirected using a console module (Due to setting the

Available functions for a console module to export to op2ext.dll are below. See the console module sample for detailed use instructions.

- mod_init()
- mod_init()
- mod_run()
- mod_destroy()

Expand All @@ -83,6 +77,7 @@ To load a custom module with Outpost 2:
3. Call 'Outpost2.exe /loadmod directoryName' when executing Outpost 2. For example, Outpost2.exe /loadmod multitek2.
4. Consider creating a .bat (batch) file that allows for loading the module without opening the command prompt.

To avoid undefined behaviour, console modules should only be stored as a child of Outpost 2's root directory (not further nested or outside of the game's root directory). When calling /loadmod, no trailing or prefixed directory separator should be used. IE do not call `/loadmod testmodule\` or `/loadmod .\testmodule`. A proper call would be '/loadmod testmodule'.

.ini Modules
------------------------------------------
Expand Down
5 changes: 5 additions & 0 deletions TestModule/DllMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ EXPORT void mod_init()
EXPORT void mod_run()
{
OutputDebugString("Test Module mod_run called.\n");

TestIsModuleLoaded();
TestIsConsoleModuleLoaded();
TestIsIniModuleLoaded();
TestGetLoadedModuleNames();
}

EXPORT void mod_destroy()
Expand Down
74 changes: 74 additions & 0 deletions TestModule/TestFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <cstddef>
#include <vector>

std::string GetOP2IniPath();
std::string GetGameDirStdString();
Expand Down Expand Up @@ -105,3 +106,76 @@ std::string GetGameDirStdString()

return std::string(gameDirectory);
}

void TestIsModuleLoaded()
{
const std::string moduleName("TestModule");
std::string outputString("Module " + moduleName);

if (IsModuleLoaded(moduleName.c_str())) {
outputString += " is loaded\n";
}
else {
outputString += " is not loaded\n";
}

OutputDebugString(outputString.c_str());
}

void TestIsConsoleModuleLoaded()
{
const std::string moduleName("TestModule");
std::string outputString("Console Module " + moduleName);

if (IsConsoleModuleLoaded(moduleName.c_str())) {
outputString += " is loaded\n";
}
else {
outputString += " is not loaded\n";
}

OutputDebugString(outputString.c_str());
}

void TestIsIniModuleLoaded()
{
const std::string moduleName("NetFix");
std::string outputString("Ini Module " + moduleName);

if (IsIniModuleLoaded(moduleName.c_str())) {
outputString += " is loaded\n" ;
}
else {
outputString += " is not loaded\n";
}

OutputDebugString(outputString.c_str());
}

void TestGetLoadedModuleNames()
{
const std::size_t moduleCount = GetLoadedModuleCount();
std::string outputString = "The following " + std::to_string(moduleCount) + " modules are loaded (ini and console combined):\n";
OutputDebugString(outputString.c_str());

std::vector<std::string> moduleNames;
char emptyBuffer[1];
for (std::size_t i = 0; i < moduleCount; ++i) {
const std::size_t stringLength = GetLoadedModuleName(i, emptyBuffer, 0);

std::string moduleName;
moduleName.resize(stringLength);
GetLoadedModuleName(i, &moduleName[0], stringLength);

// String concatinations (string1 + string2) will not provide expected results
// if the std::string explicity has a null terminator
moduleName.erase(std::find(moduleName.begin(), moduleName.end(), '\0'), moduleName.end());

moduleNames.push_back(moduleName);
}

for (const auto& moduleName : moduleNames) {
const std::string moduleNameOutput = " " + moduleName + "\n";
OutputDebugString(moduleNameOutput.c_str());
}
}
5 changes: 5 additions & 0 deletions TestModule/TestFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ void TestGetConsoleModDir_s();
void TestGetConsoleModDir(); //Deprecated
void TestLoadingVolumes(); //Test loading a non-existent volume & loading too many volumes
void TestIniSectionName(std::string sectionName);

void TestIsModuleLoaded();
void TestIsConsoleModuleLoaded();
void TestIsIniModuleLoaded();
void TestGetLoadedModuleNames();
10 changes: 5 additions & 5 deletions srcDLL/op2ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,16 @@ OP2EXT_API void Log(const char* message);


// Performs a case insensitive search of loaded module names, returning true if found.
// A console module's name is the name of the directory the console module is stored in.
// An ini module name is the module's [section name] within the ini file.
// See GetLoadedModuleName's description for details on how module names are formatted.
OP2EXT_API bool IsModuleLoaded(const char* moduleName);

// Performs a case insensitive comparison of the loaded console module name.
// A console module's name is the name of the directory the console module is stored in.
// Returns false if passed an empty string (Module name cannot be empty).
// See GetLoadedModuleName's description for details on how console module names are formatted.
OP2EXT_API bool IsConsoleModuleLoaded(const char* moduleName);

// Performs a case insensitive search of loaded ini module names, returning true if found.
// An ini module name is the module's [section name] within the ini file.
// See GetLoadedModuleName's description for details on how ini module names are formatted.
OP2EXT_API bool IsIniModuleLoaded(const char* moduleName);

// Returns the number of loaded modules (.ini and console combined)
Expand All @@ -80,7 +79,8 @@ OP2EXT_API size_t GetLoadedModuleCount();
// Retrieves the module name at the specified index.
// Ini modules are indexed first and console module is last.
// Use function GetLoadedModuleCount to determine how many module names to check.
// A console module's name is the name of the directory the console module is stored in.
// A console module's name is the directory name parameter passed in via the /loadmod command.
// The directory name is relative to the executable's folder, with no trailing slash
// An ini module name is the module's [section name] within the ini file.
// Returns 0 on success. Returns the required minimum size of the buffer on failure.
// If an index beyond the loaded module count is passed, returns 0 and clears the buffer.
Expand Down
12 changes: 8 additions & 4 deletions srcStatic/ConsoleModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <cstddef>

std::string moduleDirectory;
std::string moduleName;

ConsoleModuleLoader::ConsoleModuleLoader()
{
Expand All @@ -22,6 +23,7 @@ ConsoleModuleLoader::ConsoleModuleLoader(const std::string& testModuleDirectory)
OutputDebugString("Console Module constructed in test mode.");

moduleDirectory = testModuleDirectory;
moduleName = ToLower(testModuleDirectory);
}

std::string ConsoleModuleLoader::GetModuleDirectory()
Expand All @@ -31,12 +33,12 @@ std::string ConsoleModuleLoader::GetModuleDirectory()

std::string ConsoleModuleLoader::GetModuleName()
{
return ToLower(moduleDirectory);
return moduleName;
}

std::size_t ConsoleModuleLoader::Count()
{
return moduleDirectory != "" ? 1 : 0;
return moduleName != "" ? 1 : 0;
}

bool ConsoleModuleLoader::IsModuleLoaded(std::string moduleName)
Expand Down Expand Up @@ -176,9 +178,11 @@ std::string ConsoleModuleLoader::ParseLoadModCommand(std::vector<std::string> ar

try
{
std::string modRelativeDirectory = FormModRelativeDirectory(arguments);
const std::string modRelativeDirectory = FormModRelativeDirectory(arguments);

std::string modDirectory = fs::path(GetGameDirectory()).append(modRelativeDirectory).string();
moduleName = ToLower(modRelativeDirectory);

const std::string modDirectory = fs::path(GetGameDirectory()).append(modRelativeDirectory).string();

if (GetFileAttributesA(modDirectory.c_str()) == INVALID_FILE_ATTRIBUTES) {
PostErrorMessage("ConsoleModuleLoader.cpp", __LINE__, "Module directory does not exist: " + modDirectory);
Expand Down

0 comments on commit 8962314

Please sign in to comment.