forked from your-land/yl_cinema
347 lines
9.4 KiB
Lua
347 lines
9.4 KiB
Lua
-- The functions and variables in this file are only for use in the mod itself.
|
|
-- Those that do real work should be local and wrapped in public functions
|
|
-- Minetest connector
|
|
local json = yl_cinema.dependencies.json
|
|
local F = minetest.formspec_escape
|
|
yl_cinema.watching = {}
|
|
|
|
local function warn(text)
|
|
minetest.log("warning", "[yl_cinema] " .. text)
|
|
end
|
|
|
|
local function action(text)
|
|
minetest.log("action", "[yl_cinema] " .. text)
|
|
end
|
|
|
|
-- JSON decoder
|
|
local function parse_json(json_str)
|
|
return json.decode(json_str)
|
|
end
|
|
|
|
local function get_files_in_directory(folderpath)
|
|
return minetest.get_dir_list(folderpath, true)
|
|
end
|
|
|
|
-- internal functions
|
|
|
|
local function watches(playername, movie_id)
|
|
yl_cinema.watching[playername] = movie_id
|
|
end
|
|
|
|
local function watched_by(playername)
|
|
return yl_cinema.watching[playername] or ""
|
|
end
|
|
|
|
local function stops_watching(player)
|
|
local playername = player:get_player_name()
|
|
yl_cinema.watching[playername] = nil
|
|
end
|
|
|
|
local function orderpages(a, b)
|
|
return a.order < b.order
|
|
end
|
|
|
|
local function mediacallback(name)
|
|
local target_name = name or ""
|
|
action("mediacallback: File pushed to player " .. target_name)
|
|
end
|
|
|
|
local function string_to_recipe(s)
|
|
local recipe = string.split(s, ",")
|
|
if #recipe ~= 9 then
|
|
return false
|
|
end
|
|
return {{recipe[1], recipe[2], recipe[3]}, {recipe[4], recipe[5], recipe[6]}, {recipe[7], recipe[8], recipe[9]}}
|
|
end
|
|
|
|
local function path_of_movie(movie_id)
|
|
return yl_cinema.worldpath .. yl_cinema.settings.save_path .. DIR_DELIM .. movie_id .. DIR_DELIM .. movie_id ..
|
|
".json"
|
|
end
|
|
|
|
local function path_of_image(movie_id, name)
|
|
return yl_cinema.worldpath .. yl_cinema.settings.save_path .. DIR_DELIM .. movie_id .. DIR_DELIM .. "textures" ..
|
|
DIR_DELIM .. name
|
|
end
|
|
|
|
local function read_json_file(path)
|
|
local file = io.open(path, "r")
|
|
if not file then
|
|
return false, "Error opening file: " .. path
|
|
end
|
|
|
|
local content = file:read("*all")
|
|
file:close()
|
|
|
|
if not content then
|
|
return false, "Error reading file: " .. path
|
|
end
|
|
|
|
return true, parse_json(content)
|
|
end
|
|
|
|
local function get_movie(movie_id)
|
|
return yl_cinema.movies[movie_id] or {}
|
|
end
|
|
|
|
local function load_image(path)
|
|
local options = {
|
|
filepath = path
|
|
}
|
|
return minetest.dynamic_add_media(options, mediacallback)
|
|
end
|
|
|
|
local function load_images_of_movie(movie_id)
|
|
local movie = get_movie(movie_id)
|
|
local loaded_count = 0
|
|
for _, file in ipairs(movie.files) do
|
|
local path = path_of_image(movie_id, file)
|
|
local success = load_image(path)
|
|
if success then
|
|
loaded_count = loaded_count + 1
|
|
end
|
|
end
|
|
|
|
return loaded_count, #movie.files
|
|
end
|
|
|
|
local function load_movie(movie_id)
|
|
local file_path = path_of_movie(movie_id)
|
|
local success, movie_data = read_json_file(file_path)
|
|
local movie = "Error loading movie metadata from file " .. dump(file_path) .. ": " .. dump(movie_data)
|
|
if success then
|
|
movie = movie_data
|
|
else
|
|
warn(movie)
|
|
end
|
|
return success, movie
|
|
end
|
|
|
|
local function load_movies(movies_directory)
|
|
local movies = {}
|
|
local loaded_count = 0
|
|
|
|
local movie_files = get_files_in_directory(movies_directory)
|
|
for _, movie_id in ipairs(movie_files) do
|
|
local success, movie = load_movie(movie_id)
|
|
if success then
|
|
movies[movie_id] = movie
|
|
loaded_count = loaded_count + 1
|
|
end
|
|
end
|
|
|
|
return movies, loaded_count, #movie_files
|
|
end
|
|
|
|
local function search_movies(movies, search_term)
|
|
local results = {}
|
|
for movie_id, movie in pairs(movies) do
|
|
if string.match(movie_id, search_term) or string.match(movie.name, search_term) or
|
|
string.match(movie.description, search_term) then
|
|
table.insert(results, movie_id)
|
|
end
|
|
end
|
|
if #results > 0 then
|
|
return true, results
|
|
else
|
|
return false, results
|
|
end
|
|
end
|
|
|
|
local function get_movieformspec(movie_id, pagenum)
|
|
|
|
local movie = yl_cinema.get_movie(movie_id)
|
|
local screen_width = 12
|
|
local screen_height = 6.75
|
|
local screensize = screen_width .. "," .. 6.75
|
|
|
|
local formspec = {}
|
|
table.insert(formspec, "formspec_version[4]size[" .. screensize .. "]bgcolor[#000000]")
|
|
|
|
if (not movie) or (not pagenum) then
|
|
warn("Some error happened. movie=" .. dump(movie) .. ", page=" .. dump(pagenum))
|
|
table.insert(formspec, "[0.5,0.5;Some Error happened.]")
|
|
return table.concat(formspec, "")
|
|
end
|
|
|
|
if pagenum == 0 then
|
|
table.insert(formspec, "background[0,0;" .. screensize .. ";" .. (F(movie.title_texture) or "") .. ";true]")
|
|
table.insert(formspec, "label[0.5,0.5;" .. (F(movie.name) or "") .. "]")
|
|
table.insert(formspec, "textarea[0.5,1.5;" .. screensize .. ";;" .. (F(movie.description) or "") .. ";]")
|
|
else
|
|
local page = movie.pages[pagenum]
|
|
|
|
if not page then
|
|
warn("Page empty = " .. dump(page))
|
|
return ""
|
|
end
|
|
|
|
table.insert(formspec, "background[0,0;" .. screensize .. ";" .. (F(page.texture) or "") .. ";true]")
|
|
table.insert(formspec, "label[" .. (F(page.captionposx) or 0) .. "," .. (F(page.captionposy) or 0) .. ";" ..
|
|
(F(page.caption) or "") .. "]")
|
|
|
|
if pagenum == #movie.pages then
|
|
table.insert(formspec, "button[3," .. (F(screen_height) - 1) .. ";2,1;replay;Replay]")
|
|
table.insert(formspec, "button_exit[6," .. (F(screen_height) - 1) .. ";2,1;exit;Exit]")
|
|
end
|
|
|
|
end
|
|
|
|
return table.concat(formspec, "")
|
|
end
|
|
|
|
local function showpage(target_player_name, movie_id, pagenum)
|
|
|
|
if not minetest.get_player_by_name(target_player_name) then
|
|
return
|
|
end
|
|
if watched_by(target_player_name) == "" then
|
|
return
|
|
end
|
|
|
|
local formspec = get_movieformspec(movie_id, pagenum)
|
|
|
|
local movie = get_movie(movie_id)
|
|
local pages = movie.pages
|
|
|
|
if pagenum <= #pages then
|
|
|
|
table.sort(pages, orderpages)
|
|
|
|
local page = pages[pagenum] or {}
|
|
|
|
local delay = page.duration or 3
|
|
local nextpage = pagenum + 1
|
|
minetest.after(delay, showpage, target_player_name, movie_id, nextpage)
|
|
watches(target_player_name, movie_id)
|
|
minetest.show_formspec(target_player_name, "yl_cinema:movie", formspec)
|
|
end
|
|
|
|
end
|
|
|
|
--
|
|
|
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
if formname ~= "yl_cinema:movie" then
|
|
return
|
|
end
|
|
|
|
local playername = player:get_player_name()
|
|
|
|
if fields.exit or fields.quit then
|
|
stops_watching(player)
|
|
end
|
|
|
|
if player and fields.replay then
|
|
local movie_id = watched_by(playername)
|
|
showpage(player:get_player_name(), movie_id, 0)
|
|
end
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
minetest.register_on_leaveplayer(stops_watching)
|
|
minetest.register_on_dieplayer(stops_watching)
|
|
|
|
-- Chatcommands
|
|
|
|
function yl_cinema.cmd_list_movies(name, param)
|
|
|
|
local args = string.split(param, " ")
|
|
|
|
if (#args > 1) then
|
|
return false, "Usage: /listmovies [<searchstring>]"
|
|
end
|
|
|
|
local searchterm = args[1] or ""
|
|
|
|
minetest.log("action", "[yl_cinema] Player " .. name .. " searches for movie " .. searchterm)
|
|
|
|
local success, msg = yl_cinema.listmovies(searchterm)
|
|
|
|
if success then
|
|
return true, dump(msg)
|
|
else
|
|
return false, "No movies matching your criteria were found."
|
|
end
|
|
end
|
|
|
|
function yl_cinema.cmd_show_movie(name, param)
|
|
local args = string.split(param, " ")
|
|
|
|
if (#args ~= 2) then
|
|
return false, "Usage: /showmovie <playername> <movie>"
|
|
end
|
|
if not minetest.get_player_by_name(args[1]) then
|
|
return false, "Player not online"
|
|
end
|
|
|
|
local target_player_name = args[1] or ""
|
|
local movie_id = args[2] or ""
|
|
|
|
minetest.log("action", "[yl_cinema] Player " .. name .. " shows movie " .. movie_id .. " to " .. target_player_name)
|
|
|
|
local success, msg = yl_cinema.startmovie(movie_id, target_player_name)
|
|
|
|
if success then
|
|
return true, msg
|
|
else
|
|
return false, msg
|
|
end
|
|
end
|
|
|
|
function yl_cinema.listmovies(searchterm)
|
|
return search_movies(yl_cinema.movies, searchterm)
|
|
end
|
|
|
|
function yl_cinema.startmovie(movie_id, target_player_name)
|
|
local pagenum = 0
|
|
if not next(get_movie(movie_id)) then
|
|
return false, "Movie " .. movie_id .. " not found."
|
|
end
|
|
watches(target_player_name, movie_id)
|
|
-- Start to show a movie
|
|
if minetest.get_player_by_name(target_player_name) then
|
|
showpage(target_player_name, movie_id, pagenum)
|
|
return true, "Movie " .. movie_id .. " started for " .. target_player_name
|
|
else
|
|
return false, "Player " .. target_player_name .. " not found."
|
|
end
|
|
end
|
|
|
|
function yl_cinema.load(filename, ...)
|
|
return read_json_file(filename, ...)
|
|
end
|
|
|
|
function yl_cinema.load_movies(movies_directory, ...)
|
|
return load_movies(movies_directory, ...)
|
|
end
|
|
|
|
function yl_cinema.search_movies(movies, search_term, ...)
|
|
return search_movies(movies, search_term, ...)
|
|
end
|
|
|
|
function yl_cinema.path_of_movie(movie_id, ...)
|
|
return path_of_movie(movie_id, ...)
|
|
end
|
|
|
|
function yl_cinema.load_images_of_movie(movie_id, ...)
|
|
return load_images_of_movie(movie_id, ...)
|
|
end
|
|
|
|
function yl_cinema.get_movie(movie_id, ...)
|
|
return get_movie(movie_id, ...)
|
|
end
|
|
|
|
function yl_cinema.string_to_recipe(recipestring, ...)
|
|
return string_to_recipe(recipestring, ...)
|
|
end
|
|
|
|
function yl_cinema.orderpages(a, b, ...)
|
|
return orderpages(a, b, ...)
|
|
end
|
|
|
|
yl_cinema.action = action
|
|
yl_cinema.warn = warn
|