Skip to content

Commit

Permalink
Add a filesystem module
Browse files Browse the repository at this point in the history
This currently contains have_file, read_file, canonical_path, get_image_size, and new functions that work with binary_path files.
  • Loading branch information
CelticMinstrel committed May 11, 2021
1 parent 7269f57 commit 5cfc439
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 37 deletions.
15 changes: 15 additions & 0 deletions data/lua/core/filesystem.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

--[========[File Handling]========]
print("Loading filesystem module...")

filesystem.asset_type = {
IMAGE = 'images',
SOUND = 'sounds',
MUSIC = 'music',
MAP = 'maps',
}

wesnoth.have_file = wesnoth.deprecate_api('wesnoth.have_file', 'filesystem.have_file', 1, nil, filesystem.have_file)
wesnoth.read_file = wesnoth.deprecate_api('wesnoth.read_file', 'filesystem.read_file', 1, nil, filesystem.read_file)
wesnoth.canonical_path = wesnoth.deprecate_api('wesnoth.canonical_path', 'filesystem.canonical_path', 1, nil, filesystem.canonical_path)
wesnoth.get_image_size = wesnoth.deprecate_api('wesnoth.get_image_size', 'filesystem.image_size', 1, nil, filesystem.image_size)
12 changes: 6 additions & 6 deletions data/lua/package.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ local mt = {
local empty_pkg = setmetatable({}, mt)

local function resolve_package(pkg_name)
pkg_name = wesnoth.canonical_path(pkg_name)
pkg_name = filesystem.canonical_path(pkg_name)
if pkg_name[#pkg_name] == '/' then
pkg_name = pkg_name:sub(1, -2)
end
if wesnoth.have_file(pkg_name) then return pkg_name end
if filesystem.have_file(pkg_name) then return pkg_name end
if pkg_name:sub(-4) ~= ".lua" then
local test = resolve_package(pkg_name .. ".lua")
if test then return test end
end
if pkg_name:sub(1, 4) ~= "lua/" then
if wesnoth.have_file("lua/" .. pkg_name) then
if filesystem.have_file("lua/" .. pkg_name) then
return "lua/" .. pkg_name
end
end
if pkg_name:sub(1, 2) ~= "./" then
if wesnoth.have_file("./" .. pkg_name) then
if filesystem.have_file("./" .. pkg_name) then
return "./" .. pkg_name
end
end
Expand All @@ -49,12 +49,12 @@ function wesnoth.require(pkg_name)
end

-- Next, if it's a single file, load the package with dofile
if wesnoth.have_file(loaded_name, true) then
if filesystem.have_file(loaded_name, true) then
local pkg = wesnoth.dofile(loaded_name)
wesnoth.package[loaded_name] = pkg or empty_pkg
return pkg
else -- If it's a directory, load all the files therein
local files = wesnoth.read_file(loaded_name)
local files = filesystem.read_file(loaded_name)
local pkg = {}
for i = files.ndirs + 1, #files do
if files[i]:sub(-4) == ".lua" then
Expand Down
4 changes: 2 additions & 2 deletions src/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1553,9 +1553,9 @@ std::string get_short_wml_path(const std::string& filename)
return filename;
}

std::string get_independent_image_path(const std::string& filename)
std::string get_independent_binary_file_path(const std::string& type, const std::string& filename)
{
bfs::path full_path(get_binary_file_location("images", filename));
bfs::path full_path(get_binary_file_location(type, filename));

if(full_path.empty()) {
return full_path.generic_string();
Expand Down
6 changes: 3 additions & 3 deletions src/filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,13 +435,13 @@ std::string get_wml_location(const std::string &filename,
std::string get_short_wml_path(const std::string &filename);

/**
* Returns an image path to @a filename for binary path-independent use in saved games.
* Returns an asset path to @a filename for binary path-independent use in saved games.
*
* Example:
* units/konrad-fighter.png ->
* images, units/konrad-fighter.png ->
* data/campaigns/Heir_To_The_Throne/images/units/konrad-fighter.png
*/
std::string get_independent_image_path(const std::string &filename);
std::string get_independent_binary_file_path(const std::string& type, const std::string &filename);

/**
* Returns the appropriate invocation for a Wesnoth-related binary, assuming
Expand Down
2 changes: 1 addition & 1 deletion src/gui/dialogs/game_load.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ void game_load::display_savegame_internal(const savegame::save_info& game)
// work, we fallback on unknown-unit.png.
std::string leader_image = leader["leader_image"].str();
if(!::image::exists(leader_image)) {
leader_image = filesystem::get_independent_image_path(leader_image);
leader_image = filesystem::get_independent_binary_file_path("images", leader_image);

// The leader TC modifier isn't appending if the independent image path can't
// be resolved during save_index entry creation, so we need to add it here.
Expand Down
4 changes: 2 additions & 2 deletions src/save_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,11 +493,11 @@ void extract_summary_from_config(config& cfg_save, config& cfg_summary)

// We need a binary path-independent path to the leader image here so it can be displayed
// for campaign-specific units even when the campaign isn't loaded yet.
std::string leader_image_path = filesystem::get_independent_image_path(leader_image);
std::string leader_image_path = filesystem::get_independent_binary_file_path("images", leader_image);

// If the image path was found, we append the leader TC modifier. If it's not (such as in
// the case where the binary path hasn't been loaded yet, perhaps due to save_index being
// deleted), the unaltered image path is used and will be parsed by get_independent_image_path
// deleted), the unaltered image path is used and will be parsed by get_independent_binary_file_path
// at runtime.
if(!leader_image_path.empty()) {
leader_image_path += leader_image_tc_modifier;
Expand Down
59 changes: 59 additions & 0 deletions src/scripting/lua_fileops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "log.hpp"
#include "scripting/lua_common.hpp" // for chat_message, luaW_pcall
#include "scripting/push_check.hpp"
#include "picture.hpp"
#include "sdl/surface.hpp"

#include <algorithm>
#include <exception>
Expand All @@ -35,6 +37,48 @@ static lg::log_domain log_scripting_lua("scripting/lua");
#define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
#define ERR_LUA LOG_STREAM(err, log_scripting_lua)

/**
* Gets the dimension of an image.
* - Arg 1: string.
* - Ret 1: width.
* - Ret 2: height.
*/
static int intf_get_image_size(lua_State *L)
{
char const *m = luaL_checkstring(L, 1);
image::locator img(m);
if(!img.file_exists()) return 0;
surface s = get_image(img);
lua_pushinteger(L, s->w);
lua_pushinteger(L, s->h);
return 2;
}

/**
* Returns true if an asset with the given path can be found in the binary paths.
* - Arg 1: asset type (generally one of images, sounds, music, maps)
* - Arg 2: relative path
*/
static int intf_have_asset(lua_State* L)
{
std::string type = luaL_checkstring(L, 1), name = luaL_checkstring(L, 2);
lua_pushboolean(L, !filesystem::get_binary_file_location(type, name).empty());
return 1;
}

/**
* Given an asset path relative to binary paths, resolves to an absolute
* asset path starting from data/
* - Arg 1: asset type
* - Arg 2: relative path
*/
static int intf_resolve_asset(lua_State* L)
{
std::string type = luaL_checkstring(L, 1), name = luaL_checkstring(L, 2);
lua_push(L, filesystem::get_independent_binary_file_path(type, name));
return 1;
}

namespace lua_fileops {
static std::string get_calling_file(lua_State* L)
{
Expand Down Expand Up @@ -275,4 +319,19 @@ int load_file(lua_State *L)
return 1;
}

int luaW_open(lua_State* L)
{
static luaL_Reg const callbacks[] {
{ "have_file", &lua_fileops::intf_have_file },
{ "read_file", &lua_fileops::intf_read_file },
{ "canonical_path", &lua_fileops::intf_canonical_path },
{ "image_size", &intf_get_image_size },
{ "have_asset", &intf_have_asset },
{ "resolve_asset", &intf_resolve_asset },
};
lua_newtable(L);
luaL_setfuncs(L, callbacks, 0);
return 1;
}

} // end namespace lua_fileops
1 change: 1 addition & 0 deletions src/scripting/lua_fileops.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ int intf_have_file(lua_State*);
int intf_read_file(lua_State*);
int intf_canonical_path(lua_State*);
int load_file(lua_State*);
int luaW_open(lua_State *L);

} // end namespace lua_fileops
22 changes: 1 addition & 21 deletions src/scripting/lua_kernel_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
#include "scripting/push_check.hpp"

#include "game_version.hpp" // for do_version_check, etc
#include "picture.hpp"

#include <functional>
#include "utils/name_generator.hpp"
Expand Down Expand Up @@ -432,22 +431,6 @@ static int intf_deprecated_message(lua_State* L) {
return 0;
}

/**
* Gets the dimension of an image.
* - Arg 1: string.
* - Ret 1: width.
* - Ret 2: height.
*/
static int intf_get_image_size(lua_State *L) {
char const *m = luaL_checkstring(L, 1);
image::locator img(m);
if(!img.file_exists()) return 0;
surface s = get_image(img);
lua_pushinteger(L, s->w);
lua_pushinteger(L, s->h);
return 2;
}

/**
* Returns the time stamp, exactly as [set_variable] time=stamp does.
* - Ret 1: integer
Expand Down Expand Up @@ -507,6 +490,7 @@ lua_kernel_base::lua_kernel_base()
{ "mathx", lua_mathx::luaW_open },
{ "wml", lua_wml::luaW_open },
{ "gui", lua_gui2::luaW_open },
{ "filesystem", lua_fileops::luaW_open },
{ nullptr, nullptr }
};
for (luaL_Reg const *lib = safe_libs; lib->func; ++lib)
Expand Down Expand Up @@ -546,9 +530,6 @@ lua_kernel_base::lua_kernel_base()

static luaL_Reg const callbacks[] {
{ "deprecated_message", &intf_deprecated_message },
{ "have_file", &lua_fileops::intf_have_file },
{ "read_file", &lua_fileops::intf_read_file },
{ "canonical_path", &lua_fileops::intf_canonical_path },
{ "textdomain", &lua_common::intf_textdomain },
{ "dofile", &dispatch<&lua_kernel_base::intf_dofile> },
{ "require", &dispatch<&lua_kernel_base::intf_require> },
Expand All @@ -557,7 +538,6 @@ lua_kernel_base::lua_kernel_base()
{ "eval_formula", &lua_formula_bridge::intf_eval_formula},
{ "name_generator", &intf_name_generator },
{ "log", &intf_log },
{ "get_image_size", &intf_get_image_size },
{ "ms_since_init", &intf_ms_since_init },
{ "get_language", &intf_get_language },
{ "version", &intf_make_version },
Expand Down
4 changes: 2 additions & 2 deletions src/tests/test_filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE( test_fs_binary_path )
BOOST_CHECK_EQUAL( get_binary_file_location("sounds", "explosion.ogg"),
gamedata + "/data/core/sounds/explosion.ogg" );

BOOST_CHECK_EQUAL( get_independent_image_path("wesnoth-icon.png"),
BOOST_CHECK_EQUAL( get_independent_binary_file_path("images", "wesnoth-icon.png"),
"data/core/images/wesnoth-icon.png" );

// Inexistent paths are resolved empty.
Expand All @@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE( test_fs_binary_path )
BOOST_CHECK( get_binary_file_location("images", "bunnies_and_ponies_and_rainbows_oh_em_gee.psd").empty() );
BOOST_CHECK( get_binary_file_location("music", "this_track_does_not_exist.aiff").empty() );
BOOST_CHECK( get_binary_file_location("sounds", "rude_noises.aiff").empty() );
BOOST_CHECK( get_independent_image_path("dopefish.txt").empty() );
BOOST_CHECK( get_independent_binary_file_path("images", "dopefish.txt").empty() );
}

BOOST_AUTO_TEST_CASE( test_fs_wml_path )
Expand Down

0 comments on commit 5cfc439

Please sign in to comment.