• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Return-To-The-Roots / s25client / 14284294327

05 Apr 2025 05:41PM UTC coverage: 50.311% (+0.02%) from 50.288%
14284294327

Pull #1750

github

web-flow
Merge 6b1072a28 into c8cf430f2
Pull Request #1750: Fix size of Settings window

8 of 26 new or added lines in 15 files covered. (30.77%)

7 existing lines in 2 files now uncovered.

22370 of 44463 relevant lines covered (50.31%)

35678.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.44
/libs/libGamedata/lua/GameDataLoader.cpp
1
// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org)
2
//
3
// SPDX-License-Identifier: GPL-2.0-or-later
4

5
#include "GameDataLoader.h"
6
#include "CheckedLuaTable.h"
7
#include "RttrConfig.h"
8
#include "files.h"
9
#include "helpers/containerUtils.h"
10
#include "helpers/format.hpp"
11
#include "gameData/EdgeDesc.h"
12
#include "gameData/LandscapeDesc.h"
13
#include "gameData/TerrainDesc.h"
14
#include "gameData/WorldDescription.h"
15
#include "s25util/Log.h"
16
#include <kaguya/kaguya.hpp>
17
#include <boost/filesystem.hpp>
18
#include <iostream>
19
#include <stdexcept>
20

21
namespace bfs = boost::filesystem;
22

23
GameDataLoader::GameDataLoader(WorldDescription& worldDesc, const boost::filesystem::path& basePath)
205✔
24
    : worldDesc_(worldDesc), basePath_(basePath.lexically_normal().make_preferred()), curIncludeDepth_(0),
410✔
25
      errorInIncludeFile_(false)
615✔
26
{
27
    Register(lua);
205✔
28

29
    lua["rttr"] = this;
205✔
30
    lua["include"] = kaguya::function([this](const std::string& file) { Include(file); });
824✔
31
}
205✔
32

33
GameDataLoader::GameDataLoader(WorldDescription& worldDesc)
198✔
34
    : GameDataLoader(worldDesc, RTTRCONFIG.ExpandPath(s25::folders::gamedata) / "world")
396✔
35
{}
198✔
36

37
GameDataLoader::~GameDataLoader() = default;
205✔
38

39
bool GameDataLoader::Load()
206✔
40
{
41
    curFile_ = basePath_ / "default.lua";
412✔
42
    curIncludeDepth_ = 0;
206✔
43
    errorInIncludeFile_ = false;
206✔
44
    try
45
    {
46
        bool res = loadScript(curFile_);
206✔
47
        std::cerr << "Loaded " << curFile_ << ':' << res << std::endl;
206✔
48
        if(!res)
206✔
49
            return false;
5✔
NEW
50
    } catch(const std::exception& e)
×
51
    {
UNCOV
52
        LOG.write("Failed to load game data!\nReason: %1%\nCurrent file being processed: %2%\n") % e.what() % curFile_;
×
53
        return false;
×
54
    }
55
    std::cerr << "Loade2d " << curFile_ << ':' << !errorInIncludeFile_ << std::endl;
201✔
56
    return !errorInIncludeFile_;
201✔
57
}
58

59
void GameDataLoader::Register(kaguya::State& state)
205✔
60
{
61
    state["RTTRGameData"].setClass(kaguya::UserdataMetatable<GameDataLoader, LuaInterfaceBase>()
410✔
62
                                     .addFunction("AddLandscape", &GameDataLoader::AddLandscape)
205✔
63
                                     .addFunction("AddTerrainEdge", &GameDataLoader::AddTerrainEdge)
205✔
64
                                     .addFunction("AddTerrain", &GameDataLoader::AddTerrain));
205✔
65
}
205✔
66

67
class LuaIncludeError : public std::runtime_error
68
{
69
public:
70
    using std::runtime_error::runtime_error;
71
};
72

73
void GameDataLoader::Include(const std::string& filepath)
619✔
74
{
75
    try
76
    {
77
        constexpr int maxIncludeDepth = 10;
619✔
78
        // Protect against cycles and stack overflows
79
        if(++curIncludeDepth_ >= maxIncludeDepth)
619✔
80
            throw LuaIncludeError(helpers::format("Maximum include depth of %1% is reached!", maxIncludeDepth));
2✔
81
        const auto isAllowedChar = [](const char c) {
8,316✔
82
            return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '/'
8,316✔
83
                   || c == '.';
16,632✔
84
        };
85
        if(helpers::contains_if(filepath, [isAllowedChar](const char c) { return !isAllowedChar(c); }))
8,933✔
86
            throw LuaIncludeError("It contains disallowed chars. Allowed: alpha-numeric, underscore, slash and dot.");
1✔
87
        if(bfs::path(filepath).is_absolute())
616✔
88
            throw LuaIncludeError("Path to file must be relative to current file");
1✔
89
        bfs::path absFilePath = bfs::absolute(filepath, curFile_.parent_path());
1,845✔
90
        if(!bfs::is_regular_file(absFilePath))
615✔
91
            throw LuaIncludeError("File not found!");
1✔
92

93
        // Normalize for below check against basePath
94
        absFilePath = absFilePath.lexically_normal().make_preferred();
614✔
95
        if(absFilePath.extension() != ".lua")
1,228✔
96
            throw LuaIncludeError("File must have .lua as the extension!");
1✔
97
        if(absFilePath.string().find(basePath_.string()) != 0)
613✔
98
            throw LuaIncludeError("File is outside the lua data directory!");
1✔
99
        const auto oldCurFile = curFile_;
612✔
100
        curFile_ = absFilePath;
612✔
101
        errorInIncludeFile_ |= !loadScript(absFilePath);
612✔
102
        curFile_ = oldCurFile;
612✔
103
        RTTR_Assert(curIncludeDepth_ > 0);
612✔
104
        --curIncludeDepth_;
612✔
105
    } catch(const LuaIncludeError& e)
14✔
106
    {
107
        throw std::runtime_error(helpers::format("Include file '%1%' cannot be included: %2%", filepath, e.what()));
7✔
108
    }
109
}
612✔
110

111
void GameDataLoader::AddLandscape(const kaguya::LuaTable& data)
595✔
112
{
113
    worldDesc_.landscapes.add(LandscapeDesc(data, worldDesc_));
595✔
114
}
595✔
115

116
void GameDataLoader::AddTerrainEdge(const kaguya::LuaTable& data)
2,773✔
117
{
118
    worldDesc_.edges.add(EdgeDesc(data, worldDesc_));
2,773✔
119
}
2,773✔
120

121
void GameDataLoader::AddTerrain(const kaguya::LuaTable& data)
13,863✔
122
{
123
    worldDesc_.terrain.add(TerrainDesc(data, worldDesc_));
13,863✔
124
}
13,863✔
125

126
void loadGameData(WorldDescription& worldDesc)
183✔
127

128
{
129
    GameDataLoader gdLoader(worldDesc);
366✔
130
    if(!gdLoader.Load())
183✔
UNCOV
131
        throw std::runtime_error("Failed to load game data");
×
132
}
183✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc