diff --git a/game/engine/ButtonList.lua b/game/engine/ButtonList.lua index 944ed5490256a1184223d8187e5f4b93de800d02..0ceeb9d7d152bce2db43ae8225653f65e849a074 100644 --- a/game/engine/ButtonList.lua +++ b/game/engine/ButtonList.lua @@ -106,6 +106,7 @@ function _M:select(i, offset) end if self.selected > #self.list then self.selected = 1 end if self.selected < 1 then self.selected = #self.list end + print(self.list,self.selected) if old ~= self.selected and self.list[self.selected].onSelect then self.list[self.selected].onSelect() end self.changed = true end diff --git a/game/engine/Module.lua b/game/engine/Module.lua index 2180fc4dd7274126fe8cc91719f1c849ce0011b6..2aa87b442857160afd61d805feda5869d5bab16d 100644 --- a/game/engine/Module.lua +++ b/game/engine/Module.lua @@ -93,6 +93,7 @@ function _M:loadDefinition(dir, team) fs.mount(src, "/", false) end + profile:loadModuleProfile(mod.short_name) local m = require(mod.starter) print("[MODULE LOADER] loading module", mod.long_name, "["..mod.starter.."]", "::", m[1] and m[1].__CLASSNAME, m[2] and m[2].__CLASSNAME) return m[1], m[2] @@ -192,7 +193,14 @@ function _M:loadRemoteList(src) end end setfenv(f, dmods) - f() + local ok, err = pcall(f) + if not ok and err then + print("Could not read modules list from ", src, ":", err) + l:send("moduleslist", {}) + return + end + + for k, e in ipairs(list) do print("[INSTALLABLE MODULE] ", e.name) end l:send("moduleslist", list) end diff --git a/game/engine/PlayerProfile.lua b/game/engine/PlayerProfile.lua new file mode 100644 index 0000000000000000000000000000000000000000..ea934b7780882591d664d15c89aa4871a89c0bf8 --- /dev/null +++ b/game/engine/PlayerProfile.lua @@ -0,0 +1,177 @@ +-- TE4 - T-Engine 4 +-- Copyright (C) 2009, 2010 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +require "engine.class" +local http = require "socket.http" +local url = require "socket.url" +local ltn12 = require "ltn12" +require "Json2" + +--- Handles the player profile, possible online +module(..., package.seeall, class.make) + +function _M:init(name) + self.generic = {} + self.modules = {} + self.name = name or "default" + self:loadGenericProfile() + + self.auth = false + + if self.generic.online then + self.login = self.generic.online.login + self.pass = self.generic.online.pass + self:tryAuth() + self:getConfigs("generic") + end +end + +function _M:loadData(f, where) + setfenv(f, where) + local ok, err = pcall(f) + if not ok and err then error(err) end +end + +--- Loads profile generic profile from disk +function _M:loadGenericProfile() + local d = "/profiles/"..self.name.."/generic/" + fs.mount(engine.homepath, "/") + + for i, file in ipairs(fs.list(d)) do + if file:find(".profile$") then + local f, err = loadfile(d..file) + if not f and err then error(err) end + local field = file:gsub(".profile$", "") + self.generic[field] = self.generic[field] or {} + self:loadData(f, self.generic[field]) + end + end + + fs.umount(engine.homepath) +end + +--- Loads profile module profile from disk +function _M:loadModuleProfile(short_name) + local d = "/profiles/"..self.name.."/modules/"..short_name.."/" + fs.mount(engine.homepath, "/") + + self.modules[short_name] = self.modules[short_name] or {} + + for i, file in ipairs(fs.list(d)) do + if file:find(".profile$") then + local f, err = loadfile(d..file) + if not f and err then error(err) end + local field = file:gsub(".profile$", "") + self.modules[short_name][field] = self.modules[short_name][field] or {} + self:loadData(f, self.modules[short_name][field]) + end + end + + fs.umount(engine.homepath) + + self:getConfigs(short_name) + + self.mod = self.modules[short_name] + self.mod_name = short_name +end + +--- Saves a profile data +function _M:saveGenericProfile(name, data) + -- Check for readability + local f, err = loadstring(data) + if not f then print("[PROFILES] cannot save generic data ", name, data, "it does not parse:") error(err) end + local ok, err = pcall(f) + if not ok and err then print("[PROFILES] cannot save generic data", name, data, "it does not parse") error(err) end + + local restore = fs.getWritePath() + fs.setWritePath(engine.homepath) + fs.mkdir("/profiles/"..self.name.."/generic/") + local f = fs.open("/profiles/"..self.name.."/generic/"..name..".profile", "w") + f:write(data) + f:close() + if restore then fs.setWritePath(restore) end + + self:setConfigs("generic", name, data) +end + +--- Saves a module profile data +function _M:saveModuleProfile(name, data) + -- Check for readability + local f, err = loadstring(data) + if not f then print("[PROFILES] cannot save module data ", name, data, "it does not parse:") error(err) end + local ok, err = pcall(f) + if not ok and err then print("[PROFILES] cannot save module data", name, data, "it does not parse") error(err) end + + local restore = fs.getWritePath() + fs.setWritePath(engine.homepath) + fs.mkdir("/profiles/"..self.name.."/modules/") + fs.mkdir("/profiles/"..self.name.."/modules/"..self.mod_name.."/") + local f = fs.open("/profiles/"..self.name.."/modules/"..self.mod_name.."/"..name..".profile", "w") + f:write(data) + f:close() + if restore then fs.setWritePath(restore) end + + self:setConfigs(self.mod_name, name, data) +end + + +----------------------------------------------------------------------- +-- Online stuff +----------------------------------------------------------------------- + +function _M:rpc(data) + local body, status = http.request("http://te4.org/lua/profilesrpc.ws/"..data.action, "json="..url.escape(json.encode(data))) + if not body then return end + return json.decode(body) +end + +function _M:tryAuth() + local data = self:rpc{action="TryAuth", login=self.login, pass=self.pass} + if not data then print("[ONLINE PROFILE] not auth") return end + print("[ONLINE PROFILE] auth as ", data.name) + self.auth = data +end + +function _M:getConfigs(module) + if not self.auth then return end + local data = self:rpc{action="GetConfigs", login=self.login, pass=self.pass, module=module} + if not data then print("[ONLINE PROFILE] get configs") return end + for name, val in pairs(data) do + print("[ONLINE PROFILE] config ", name) + + local field = name + local f, err = loadstring(val) + if not f and err then error(err) end + if module == "generic" then + self.generic[field] = self.generic[field] or {} + self:loadData(f, self.generic[field]) + else + self.modules[module] = self.modules[module] or {} + self.modules[module][field] = self.modules[module][field] or {} + self:loadData(f, self.modules[module][field]) + end + end +end + +function _M:setConfigs(module, name, val) + if not self.auth then return end + local data = self:rpc{action="SetConfigs", login=self.login, pass=self.pass, module=module, name=name, data=val} + if not data then return end + print("[ONLINE PROFILE] saved ", module, name) +end diff --git a/game/engine/init.lua b/game/engine/init.lua index ded3129a3ba65c36ace3637c14b843e5e9758dc8..40fdb8f4cae4bfb6a13ae95883e18fbf2c54ad46 100644 --- a/game/engine/init.lua +++ b/game/engine/init.lua @@ -30,6 +30,7 @@ require "engine.interface.GameMusic" require "engine.KeyBind" require "engine.Savefile" require "engine.Tiles" +require "engine.PlayerProfile" engine.Tiles.prefix = "/data/gfx/" -- Engine Version @@ -40,6 +41,7 @@ engine.homepath = fs.getUserPath()..fs.getPathSeparator()..fs.getHomePath()..fs. fs.setWritePath(fs.getUserPath()) fs.mkdir(fs.getHomePath()) fs.mkdir(fs.getHomePath().."/4.0/") +fs.mkdir(fs.getHomePath().."/4.0/profiles/") fs.mkdir(fs.getHomePath().."/4.0/settings/") fs.setWritePath(fs.getHomePath()) @@ -75,4 +77,7 @@ game = false engine.Game:setResolution(config.settings.window.size) engine.interface.GameMusic:soundSystemStatus(config.settings.sound.enabled, true) +-- Load profile configs +profile = engine.PlayerProfile.new() + util.showMainMenu(true) diff --git a/game/engine/interface/WorldAchievements.lua b/game/engine/interface/WorldAchievements.lua index c191a0076bd12579dab17e6c9712706600148219..d5c0186b253928fb9cf64525b8c16a6cbc39aa60 100644 --- a/game/engine/interface/WorldAchievements.lua +++ b/game/engine/interface/WorldAchievements.lua @@ -54,8 +54,17 @@ function _M:newAchievement(t) print("[ACHIEVEMENT] defined", t.order, t.id) end -function _M:init() +function _M:loadAchievements() self.achieved = {} + + for k, e in pairs(profile.mod) do + if k:find('^achievement_') then + local id = k:gsub('^achievement_', '') + if self.achiev_defs[id] then + self.achieved[id] = e + end + end + end end function _M:getAchievementFromId(id) @@ -88,6 +97,7 @@ function _M:gainAchievement(id, src, ...) if not a.can_gain(data, src, ...) then return end end + profile:saveModuleProfile("achievement_"..id, ("turn=%d\nwho=%q\nwhen=%q\n"):format(game.turn, self:achievementWho(src), os.date("%Y-%m-%d %H:%M:%S"))) self.achieved[id] = {turn=game.turn, who=self:achievementWho(src), when=os.date("%Y-%m-%d %H:%M:%S")} game.log("#LIGHT_GREEN#New Achievement: %s!", a.name) Dialog:simplePopup("New Achievement: #LIGHT_GREEN#"..a.name, a.desc) diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 89417a78aab6cc186ad02ed9c0f1d5e460524c75..c31ac256f7d2230d816109ffc2c188999f2e59f0 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -503,7 +503,10 @@ function _M:setupCommands() self.key:addCommands{ [{"_d","ctrl"}] = function() - if config.settings.tome.cheat then self:changeLevel(1, "test") end + if config.settings.tome.cheat then + self:changeLevel(1, "test") + self:setAllowedBuild("mage", true) + end end, } self.key:addBinds @@ -823,15 +826,15 @@ function _M:setAllowedBuild(what, notify) -- Do not unlock things in easy mode --if game.difficulty == game.DIFFICULTY_EASY then return end - config.settings.tome = config.settings.tome or {} - config.settings.tome.allow_build = config.settings.tome.allow_build or {} - if config.settings.tome.allow_build[what] then return false end - config.settings.tome.allow_build[what] = true + profile.mod.allow_build = profile.mod.allow_build or {} + if profile.mod.allow_build[what] then return end + profile.mod.allow_build[what] = true + local t = {} - for k, e in pairs(config.settings.tome.allow_build) do - t[#t+1] = ("tome.allow_build.%s = %s"):format(k, tostring(e)) + for k, e in pairs(profile.mod.allow_build) do + t[#t+1] = ("%s = %s"):format(k, tostring(e)) end - game:saveSettings("tome.allow_build", table.concat(t, "\n")) + profile:saveModuleProfile("allow_build", table.concat(t, "\n")) if notify then self:registerDialog(require("mod.dialogs.UnlockDialog").new(what)) diff --git a/game/modules/tome/class/World.lua b/game/modules/tome/class/World.lua index 2d109ce952f8762833fed674a8d549304d5aec53..bd90f904c1c422e0b7aff40f61316e579871bd7a 100644 --- a/game/modules/tome/class/World.lua +++ b/game/modules/tome/class/World.lua @@ -26,7 +26,10 @@ module(..., package.seeall, class.inherit(engine.World, engine.interface.WorldAc function _M:init() engine.World.init(self) - engine.interface.WorldAchievements.init(self) +end + +function _M:run() + self:loadAchievements() end --- Requests the world to save diff --git a/game/modules/tome/data/birth/classes/wilder.lua b/game/modules/tome/data/birth/classes/wilder.lua index e238b53a2eed5c70e9938bb8495d5c426f6a0bad..589d622cef039d2c5a9e6687ef91986ae7e67934 100644 --- a/game/modules/tome/data/birth/classes/wilder.lua +++ b/game/modules/tome/data/birth/classes/wilder.lua @@ -29,8 +29,8 @@ newBirthDescriptor{ subclass = { __ALL__ = "never", - Summoner = function() return config.settings.tome.allow_build.wilder_summoner and "allow" or "never" end, - Wyrmic = function() return config.settings.tome.allow_build.wilder_wyrmic and "allow" or "never" end, + Summoner = function() return profile.mod.allow_build.wilder_summoner and "allow" or "never" end, + Wyrmic = function() return profile.mod.allow_build.wilder_wyrmic and "allow" or "never" end, }, }, copy = { diff --git a/game/modules/tome/data/birth/descriptors.lua b/game/modules/tome/data/birth/descriptors.lua index 7d7b88206ec9a9bfbd4df0d520e1ed1335ae65cf..83edfff5bf74892cfd216015b3c72eae079acd96 100644 --- a/game/modules/tome/data/birth/descriptors.lua +++ b/game/modules/tome/data/birth/descriptors.lua @@ -27,7 +27,7 @@ newBirthDescriptor{ world = { Arda = "allow", - ["Spydrë"] = function() return config.settings.tome.allow_build.world_spydre and "allow" or "never" end, + ["Spydrë"] = function() return profile.mod.allow_build.world_spydre and "allow" or "never" end, }, }, talents = {}, diff --git a/game/modules/tome/data/birth/races/undead.lua b/game/modules/tome/data/birth/races/undead.lua index 10030e20c25e71cae2cf5be92035e4434d3628bc..079196ec2fbb0242834dba2c23da3c6b93e53598 100644 --- a/game/modules/tome/data/birth/races/undead.lua +++ b/game/modules/tome/data/birth/races/undead.lua @@ -32,10 +32,10 @@ newBirthDescriptor{ subrace = { __ALL__ = "never", - Ghoul = function() return config.settings.tome.allow_build.undead_ghoul and "allow" or "never" end, - Skeleton = function() return config.settings.tome.allow_build.undead_skeleton and "allow" or "never" end, - Vampire = function() return config.settings.tome.allow_build.undead_vampire and "allow" or "never" end, - Wight = function() return config.settings.tome.allow_build.undead_wight and "allow" or "never" end, + Ghoul = function() return profile.mod.allow_build.undead_ghoul and "allow" or "never" end, + Skeleton = function() return profile.mod.allow_build.undead_skeleton and "allow" or "never" end, + Vampire = function() return profile.mod.allow_build.undead_vampire and "allow" or "never" end, + Wight = function() return profile.mod.allow_build.undead_wight and "allow" or "never" end, }, }, copy = { diff --git a/game/modules/tome/data/birth/worlds.lua b/game/modules/tome/data/birth/worlds.lua index 400db81115864d836595669b4dd06e4133fafba1..b0d3a123eadbd226e816071ebb8d22998c2ee6bd 100644 --- a/game/modules/tome/data/birth/worlds.lua +++ b/game/modules/tome/data/birth/worlds.lua @@ -38,18 +38,18 @@ newBirthDescriptor{ Elf = "allow", Dwarf = "allow", Hobbit = "allow", --- Orc = function() return config.settings.tome.allow_build.evil and "allow" or "never" end, --- Troll = function() return config.settings.tome.allow_build.evil and "allow" or "never" end, - Undead = function() return config.settings.tome.allow_build.undead and "allow" or "never" end, +-- Orc = function() return profile.mod.allow_build.evil and "allow" or "never" end, +-- Troll = function() return profile.mod.allow_build.evil and "allow" or "never" end, + Undead = function() return profile.mod.allow_build.undead and "allow" or "never" end, }, class = { __ALL__ = "allow", - Mage = function() return config.settings.tome.allow_build.mage and "allow" or "never" end, + Mage = function() return profile.mod.allow_build.mage and "allow" or "never" end, Wilder = function() return ( - config.settings.tome.allow_build.wilder_summoner or - config.settings.tome.allow_build.wilder_wyrmic + profile.mod.allow_build.wilder_summoner or + profile.mod.allow_build.wilder_wyrmic ) and "allow" or "never" end, }, @@ -71,7 +71,7 @@ newBirthDescriptor{ { __ALL__ = "never", Human = "allow", --- Spider = function() return config.settings.tome.allow_build.spider and "allow" or "never" end, +-- Spider = function() return profile.mod.allow_build.spider and "allow" or "never" end, }, }, } diff --git a/game/modules/tome/load.lua b/game/modules/tome/load.lua index 0299be7b4b3b5ae9e90c5cb3be1c3a27c85d957e..2b6091b5d8129ed42e5f512dd790e547417b1586 100644 --- a/game/modules/tome/load.lua +++ b/game/modules/tome/load.lua @@ -33,7 +33,7 @@ local Store = require "mod.class.Store" local WorldAchievements = require "engine.interface.WorldAchievements" config.settings.tome = config.settings.tome or {} -config.settings.tome.allow_build = config.settings.tome.allow_build or {} +profile.mod.allow_build = profile.mod.allow_build or {} -- Achievements WorldAchievements:loadDefinition("/data/achievements/") diff --git a/game/special/mainmenu/class/Game.lua b/game/special/mainmenu/class/Game.lua index 5785cf9bb9ed000d3da077495a6b6e6fac3943e3..0f0ee71200ab3afc25b541af230c541498b15314 100644 --- a/game/special/mainmenu/class/Game.lua +++ b/game/special/mainmenu/class/Game.lua @@ -29,6 +29,7 @@ local DownloadDialog = require "engine.dialogs.DownloadDialog" module(..., package.seeall, class.inherit(engine.Game)) function _M:init() + self.profile_font = core.display.newFont("/data/font/VeraIt.ttf", 14) engine.Game.init(self, engine.KeyBind.new()) self.background = core.display.loadImage("/data/gfx/mainmenu/background.jpg") @@ -41,10 +42,20 @@ function _M:run() -- Setup display self:selectStepMain() + self:checkLogged() + -- Ok everything is good to go, activate the game in the engine! self:setCurrent() end +function _M:checkLogged() + if profile.auth then + self.s_log = core.display.drawStringNewSurface(self.profile_font, "Online Profile: "..profile.auth.name.."[http://te4.org/players/"..profile.auth.page.."]", 255, 255, 0) + else + self.s_log = nil + end +end + function _M:tick() return true end @@ -56,6 +67,12 @@ function _M:display() end self.step:display() self.step:toScreen(self.step.display_x, self.step.display_y) + + if self.s_log then + local w, h = self.s_log:getSize() + self.s_log:toScreen(self.w - w, self.h - h) + end + engine.Game.display(self) end @@ -133,7 +150,7 @@ function _M:selectStepMain() self:selectStepLoad() end, }, ---[[ +-- [[ { name = "Install a game module", fct = function() @@ -264,6 +281,11 @@ function _M:selectStepInstall() end end + if #dllist == 0 then + Dialog:simplePopup("No modules available", "There are no modules to install or upgrade.") + return + end + local display_module = Dialog.new("", self.w * 0.73, self.h, self.w * 0.26, 0, 255) for i, mod in ipairs(dllist) do