Skip to content

Commit

Permalink
Add new campaign description as lua file implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ottml authored and Flow86 committed Nov 6, 2023
1 parent e16983a commit 7c78227
Show file tree
Hide file tree
Showing 8 changed files with 508 additions and 0 deletions.
58 changes: 58 additions & 0 deletions libs/libGamedata/gameData/CampaignDescription.cpp
@@ -0,0 +1,58 @@
// Copyright (C) 2005 - 2023 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

#include "CampaignDescription.h"
#include "RttrConfig.h"
#include "helpers/format.hpp"
#include "lua/CheckedLuaTable.h"
#include "lua/LuaHelpers.h"
#include "mygettext/mygettext.h"

CampaignDescription::CampaignDescription(const kaguya::LuaRef& table)
{
CheckedLuaTable luaData(table);
luaData.getOrThrow(version, "version");
luaData.getOrThrow(author, "author");
luaData.getOrThrow(name, "name");
luaData.getOrThrow(shortDescription, "shortDescription");
luaData.getOrThrow(longDescription, "longDescription");
luaData.getOrThrow(image, "image");
luaData.getOrThrow(maxHumanPlayers, "maxHumanPlayers");

if(maxHumanPlayers != 1)
throw std::invalid_argument(helpers::format(_("Invalid maximum human player count: %1%"), maxHumanPlayers));

luaData.getOrThrow(difficulty, "difficulty");

if(difficulty != gettext_noop("easy") && difficulty != gettext_noop("medium") && difficulty != gettext_noop("hard"))
throw std::invalid_argument(helpers::format(_("Invalid difficulty: %1%"), difficulty));

luaData.getOrThrow(mapFolder, "mapFolder");
luaData.getOrThrow(luaFolder, "luaFolder");
lua::validatePath(mapFolder);
lua::validatePath(luaFolder);
mapNames = luaData.getOrDefault("maps", std::vector<std::string>());

luaData.checkUnused();
}

size_t CampaignDescription::getNumMaps()
{
return mapNames.size();
}

std::string CampaignDescription::getMapName(const size_t idx) const
{
return mapNames.at(idx);
}

boost::filesystem::path CampaignDescription::getLuaFilePath(const size_t idx) const
{
return (RTTRCONFIG.ExpandPath(luaFolder) / mapNames.at(idx)).replace_extension("lua");
}

boost::filesystem::path CampaignDescription::getMapFilePath(const size_t idx) const
{
return RTTRCONFIG.ExpandPath(mapFolder) / mapNames.at(idx);
}
36 changes: 36 additions & 0 deletions libs/libGamedata/gameData/CampaignDescription.h
@@ -0,0 +1,36 @@
// Copyright (C) 2005 - 2023 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once
#include <boost/filesystem/path.hpp>
#include <string>
#include <vector>

namespace kaguya {
class LuaRef;
} // namespace kaguya

struct CampaignDescription
{
std::string version;
std::string author;
std::string name;
std::string shortDescription;
std::string longDescription;
std::string image;
unsigned maxHumanPlayers = 0;
std::string difficulty;

CampaignDescription() = default;
explicit CampaignDescription(const kaguya::LuaRef& table);
size_t getNumMaps();
boost::filesystem::path getLuaFilePath(size_t idx) const;
boost::filesystem::path getMapFilePath(size_t idx) const;
std::string getMapName(size_t idx) const;

private:
std::string mapFolder;
std::string luaFolder;
std::vector<std::string> mapNames;
};
79 changes: 79 additions & 0 deletions libs/libGamedata/lua/CampaignDataLoader.cpp
@@ -0,0 +1,79 @@
// Copyright (C) 2005 - 2023 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

#include "CampaignDataLoader.h"
#include "CheckedLuaTable.h"
#include "RttrConfig.h"
#include "files.h"
#include "helpers/containerUtils.h"
#include "helpers/format.hpp"
#include "mygettext/mygettext.h"
#include "gameData/CampaignDescription.h"
#include "s25util/Log.h"
#include <kaguya/kaguya.hpp>
#include <boost/filesystem.hpp>
#include <stdexcept>

unsigned CampaignDataLoader::GetVersion()
{
return 1;
}

CampaignDataLoader::CampaignDataLoader(CampaignDescription& campaignDesc, const boost::filesystem::path& basePath)
: campaignDesc_(campaignDesc), basePath_(basePath.lexically_normal().make_preferred())
{
Register(lua);
lua["rttr"] = this;
}

CampaignDataLoader::~CampaignDataLoader() = default;

bool CampaignDataLoader::CheckScriptVersion()
{
kaguya::LuaRef func = lua["getRequiredLuaVersion"];
if(func.type() == LUA_TFUNCTION)
{
const auto scriptVersion = func.call<unsigned>();
if(scriptVersion == GetVersion())
return true;
else
{
LOG.write(_("Wrong lua script version: %1%. Current version: %2%.\n")) % scriptVersion % GetVersion();
return false;
}
} else
{
LOG.write(_("Lua script did not provide the function getRequiredLuaVersion()! It is probably outdated.\n"));
return false;
}
}

bool CampaignDataLoader::Load()
{
auto curFile_ = basePath_ / "campaign.lua";
try
{
if(!loadScript(curFile_))
return false;

if(!CheckScriptVersion())
throw std::runtime_error("Wrong lua script version.");

kaguya::LuaRef entry = lua["campaign"];
if(entry.type() != LUA_TTABLE)
throw std::runtime_error("Campaign table variable missing.");

campaignDesc_ = CampaignDescription(entry);
} catch(std::exception& e)
{
LOG.write("Failed to load campaign data!\nReason: %1%\nCurrent file being processed: %2%\n") % e.what()
% curFile_;
return false;
}
return true;
}
void CampaignDataLoader::Register(kaguya::State& state)
{
state["RTTRCampaignData"].setClass(kaguya::UserdataMetatable<CampaignDataLoader, LuaInterfaceBase>());
}
33 changes: 33 additions & 0 deletions libs/libGamedata/lua/CampaignDataLoader.h
@@ -0,0 +1,33 @@
// Copyright (C) 2005 - 2023 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "LuaInterfaceBase.h"
#include <boost/filesystem/path.hpp>

namespace kaguya {
class State;
} // namespace kaguya
struct CampaignDescription;

class CampaignDataLoader : public LuaInterfaceBase
{
public:
CampaignDataLoader(CampaignDescription& campaignDesc, const boost::filesystem::path& basePath);
~CampaignDataLoader() override;

bool CheckScriptVersion();

/// Return version of the interface. Changes here reflect breaking changes
static unsigned GetVersion();

bool Load();

static void Register(kaguya::State& state);

private:
CampaignDescription& campaignDesc_;
boost::filesystem::path basePath_;
};
1 change: 1 addition & 0 deletions tests/s25Main/CMakeLists.txt
Expand Up @@ -36,6 +36,7 @@ add_subdirectory(audio)
if(NOT RTTR_ENABLE_COVERAGE)
add_subdirectory(autoplay)
endif()
add_subdirectory(campaign)
add_subdirectory(drivers)
add_subdirectory(integration)
add_subdirectory(IO)
Expand Down
7 changes: 7 additions & 0 deletions tests/s25Main/campaign/CMakeLists.txt
@@ -0,0 +1,7 @@
# Copyright (C) 2005 - 2021 Settlers Freaks <sf-team at siedler25.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later

add_testcase(NAME campaign
LIBS s25Main testHelpers rttr::vld
)
17 changes: 17 additions & 0 deletions tests/s25Main/campaign/main.cpp
@@ -0,0 +1,17 @@
// Copyright (C) 2005 - 2023 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

#define BOOST_TEST_MODULE RTTR_CampaignData

#include <rttr/test/Fixture.hpp>
#include <boost/test/unit_test.hpp>

#if RTTR_HAS_VLD
# include <vld.h>
#endif

struct Fixture : rttr::test::Fixture
{};

BOOST_GLOBAL_FIXTURE(Fixture);

0 comments on commit 7c78227

Please sign in to comment.