diff --git a/README.md b/README.md index 5465bef..35884fc 100644 --- a/README.md +++ b/README.md @@ -4,16 +4,18 @@ mod for minetest Mod for handling in game factions and reputation. # TODO LIST -Complete the diplomacy system. - Add a show claim command (show small entity boxes like in protection mod). Make claim's depth not go to high or low. Or make it act like a protection block where you have to claim land upwards and downwards. -Make factions power max based on how many players are in the team, and players with the same ip address can not add to the power max. - Redo the parcel attack system. Remove banner code. -Make factions without parcels disband after a few hours. \ No newline at end of file +# COMPLETED BUT NEEDS TESTING LIST + +Make factions power max based on how many players are in the team, and players with the same ip address can not add to the power max. + +Make factions without parcels disband after a few hours. + +Complete the diplomacy system. \ No newline at end of file diff --git a/chatcommands.lua b/chatcommands.lua index 3a4d355..dfcc830 100644 --- a/chatcommands.lua +++ b/chatcommands.lua @@ -1,17 +1,3 @@ -------------------------------------------------------------------------------- --- factions Mod by Sapier --- --- License WTFPL --- ---! @file chatcommnd.lua ---! @brief factions chat interface ---! @copyright Sapier, agrecascino, shamoanjac, Coder12a ---! @author Sapier, agrecascino, shamoanjac, Coder12a ---! @date 2016-08-12 --- --- Contact sapier a t gmx net -------------------------------------------------------------------------------- - local send_error = function(player, message) minetest.chat_send_player(player, message) end @@ -45,6 +31,7 @@ factions.register_command = function(cmd_name, cmd, ignore_param_count) factions = {}, players = {}, strings = {}, + unknowns = {}, other = {} } if not ignore_param_count then @@ -87,9 +74,10 @@ factions.register_command = function(cmd_name, cmd, ignore_param_count) elseif argtype == "string" then table.insert(args.strings, arg) else - minetest.log("error", "Bad format definition for function "..self.name) - send_error(player, "Internal server error") - return false + table.insert(args.unknowns, arg) + --minetest.log("error", "Bad format definition for function "..self.name) + --send_error(player, "Internal server error") + --return false end end for i=2, #argv do @@ -185,7 +173,7 @@ factions.register_command ("claim", { else local parcel_faction = factions.get_parcel_faction(parcelpos) if not parcel_faction then - send_error(player, "You faction cannot claim any (more) parcel(s).") + send_error(player, "Your faction cannot claim any (more) parcel(s).") return false elseif parcel_faction.name == faction.name then send_error(player, "This parcel already belongs to your faction.") @@ -247,7 +235,7 @@ factions.register_command("version", { end },false) ---show description of faction +--show description of faction factions.register_command("info", { format = {"faction"}, description = "Shows a faction's description.", @@ -303,8 +291,16 @@ factions.register_command("create", { end local factionname = args.strings[1] if factions.can_create_faction(factionname) then + local listofenemies = {} + for i in pairs(factions.factions) do + listofenemies[i] = factions.factions[i] + end new_faction = factions.new_faction(factionname, nil) new_faction:add_player(player, new_faction.default_leader_rank) + for i in pairs(listofenemies) do + new_faction:new_enemy(listofenemies[i].name) + listofenemies[i]:new_enemy(new_faction.name) + end return true else send_error(player, "Faction cannot be created.") @@ -417,6 +413,281 @@ factions.register_command("ranks", { end },false) +factions.register_command("rank_privileges", { + description = "List available rank privileges.", + global_privileges = {"faction_user"}, + on_success = function(player, faction, pos, parcelpos, args) + minetest.chat_send_player(player, "Privileges available:\n") + for i, k in pairs(factions.permissions) do + minetest.chat_send_player(player, k .. "\n") + end + return true + end +},false) + +if factions.faction_diplomacy then + factions.register_command("send_alliance", { + description = "Send an alliance request to another faction.", + global_privileges = {"faction_user"}, + format = {"string"}, + on_success = function(player, faction, pos, parcelpos, args) + if faction:has_permission(player, "diplomacy") then + if factions.factions[args.strings[1]] then + if not factions.factions[args.strings[1]].request_inbox[faction.name] then + if faction.allies[args.strings[1]] then + send_error(player, "You are already allys.") + return false + end + if faction.enemies[args.strings[1]] then + send_error(player, "You need to be at peace in-order to send an alliance request.") + return false + end + if args.strings[1] == faction.name then + send_error(player, "You can not send an alliance to your own faction.") + return false + end + if faction.request_inbox[args.strings[1]] then + send_error(player, "Faction " .. args.strings[1] .. "has already sent a request to you.") + return false + end + factions.factions[args.strings[1]].request_inbox[faction.name] = "alliance" + factions.factions[args.strings[1]]:broadcast("An alliance request from faction " .. faction.name .. " has been sent to you.") + faction:broadcast("An alliance request was sent to faction " .. args.strings[1]) + factions.save() + else + send_error(player, "You have already sent a request.") + end + else + send_error(player, args.strings[1] .. " is not a name of a faction.") + end + else + send_error(player, "You do not have the diplomacy privilege.") + end + end + },false) + + factions.register_command("send_peace", { + description = "Send peace to another faction.", + global_privileges = {"faction_user"}, + format = {"string"}, + on_success = function(player, faction, pos, parcelpos, args) + if faction:has_permission(player, "diplomacy") then + if factions.factions[args.strings[1]] then + if not factions.factions[args.strings[1]].request_inbox[faction.name] then + if faction.allies[args.strings[1]] then + send_error(player, "You are allys.") + return false + end + if faction.at_peace_with[args.strings[1]] then + send_error(player, "You are already at peace.") + return false + end + if args.strings[1] == faction.name then + send_error(player, "You can not send a peace request to your own faction.") + return false + end + if faction.request_inbox[args.strings[1]] then + send_error(player, "Faction " .. args.strings[1] .. "has already sent a request to you.") + return false + end + factions.factions[args.strings[1]].request_inbox[faction.name] = "peace" + factions.factions[args.strings[1]]:broadcast("A peace request from faction " .. faction.name .. " has been sent to you.") + faction:broadcast("A peace request was sent to faction " .. args.strings[1]) + factions.save() + else + send_error(player, "You have already sent a request.") + end + else + send_error(player, args.strings[1] .. " is not a name of a faction.") + end + else + send_error(player, "You do not have the diplomacy privilege.") + end + end + },false) + + factions.register_command("accept", { + description = "accept an request from another faction.", + global_privileges = {"faction_user"}, + format = {"string"}, + on_success = function(player, faction, pos, parcelpos, args) + if faction:has_permission(player, "diplomacy") then + if faction.request_inbox[args.strings[1]] then + if args.strings[1] == faction.name then + send_error(player, "You can not accept an request from own faction.") + return false + end + if faction.request_inbox[args.strings[1]] == "alliance" then + faction:new_alliance(args.strings[1]) + factions.factions[args.strings[1]]:new_alliance(faction.name) + else + if faction.request_inbox[args.strings[1]] == "peace" then + faction:new_peace(args.strings[1]) + factions.factions[args.strings[1]]:new_peace(faction.name) + end + end + faction.request_inbox[args.strings[1]] = nil + factions.save() + else + send_error(player, "No request was sent to you.") + end + else + send_error(player, "You do not have the diplomacy privilege.") + end + end + },false) + + factions.register_command("refuse", { + description = "refuse an request from another faction.", + global_privileges = {"faction_user"}, + format = {"string"}, + on_success = function(player, faction, pos, parcelpos, args) + if faction:has_permission(player, "diplomacy") then + if faction.request_inbox[args.strings[1]] then + if args.strings[1] == faction.name then + send_error(player, "You can not refuse an request from your own faction.") + return false + end + faction.request_inbox[args.strings[1]] = nil + factions.factions[args.strings[1]]:broadcast("Faction " .. faction.name .. " refuse to be your ally.") + faction:broadcast("Refused an request from faction " .. args.strings[1]) + factions.save() + else + send_error(player, "No request was sent to you.") + end + else + send_error(player, "You do not have the diplomacy privilege.") + end + end + },false) + + factions.register_command("delcare_war", { + description = "Delcare war on a faction.", + global_privileges = {"faction_user"}, + format = {"string"}, + on_success = function(player, faction, pos, parcelpos, args) + if faction:has_permission(player, "diplomacy") then + if not faction.enemies[args.strings[1]] then + if args.strings[1] == faction.name then + send_error(player, "You can not delcare war on your own faction.") + return false + end + if faction.allies[args.strings[1]] then + faction:end_alliance(args.strings[1]) + factions.factions[args.strings[1]]:end_alliance(faction.name) + end + if faction.at_peace_with[args.strings[1]] then + faction:end_peace(args.strings[1]) + factions.factions[args.strings[1]]:end_peace(faction.name) + end + faction:new_enemy(args.strings[1]) + factions.factions[args.strings[1]]:new_enemy(faction.name) + factions.save() + else + send_error(player, "You are already at war.") + end + else + send_error(player, "You do not have the diplomacy privilege.") + end + end + },false) + + factions.register_command("break", { + description = "Break an alliance.", + global_privileges = {"faction_user"}, + format = {"string"}, + on_success = function(player, faction, pos, parcelpos, args) + if faction:has_permission(player, "diplomacy") then + if faction.allies[args.strings[1]] then + if args.strings[1] == faction.name then + send_error(player, "You can not break an alliance from your own faction.") + return false + end + faction:end_alliance(args.strings[1]) + factions.factions[args.strings[1]]:end_alliance(faction.name) + faction:new_peace(args.strings[1]) + factions.factions[args.strings[1]]:new_peace(faction.name) + factions.save() + else + send_error(player, "You where not allies to begin with.") + end + else + send_error(player, "You do not have the diplomacy privilege.") + end + end + },false) + + factions.register_command("inbox", { + description = "Check your diplomacy request inbox.", + global_privileges = {"faction_user"}, + on_success = function(player, faction, pos, parcelpos, args) + if faction:has_permission(player, "diplomacy") then + local empty = true + for i,k in pairs(faction.request_inbox) do + if k == "alliance" then + minetest.chat_send_player(player,"Alliance request from faction " .. i .. "\n") + else + if k == "peace" then + minetest.chat_send_player(player,"Peace request from faction " .. i .. "\n") + end + end + empty = false + end + if empty then + minetest.chat_send_player(player,"none:") + end + else + send_error(player, "You do not have the diplomacy privilege.") + end + end + },false) + + factions.register_command("allies", { + description = "Shows the factions that are allied to you.", + global_privileges = {"faction_user"}, + on_success = function(player, faction, pos, parcelpos, args) + local empty = true + for i,k in pairs(faction.allies) do + minetest.chat_send_player(player,i .. "\n") + empty = false + end + if empty then + minetest.chat_send_player(player,"none:") + end + end + },false) + + factions.register_command("at_peace_with", { + description = "Shows the factions that are at peace with you.", + global_privileges = {"faction_user"}, + on_success = function(player, faction, pos, parcelpos, args) + local empty = true + for i,k in pairs(faction.at_peace_with) do + minetest.chat_send_player(player,i .. "\n") + empty = false + end + if empty then + minetest.chat_send_player(player,"none:") + end + end + },false) + + factions.register_command("enemies", { + description = "Shows enemies of your faction.", + global_privileges = {"faction_user"}, + on_success = function(player, faction, pos, parcelpos, args) + local empty = true + for i,k in pairs(faction.enemies) do + minetest.chat_send_player(player,i .. "\n") + empty = false + end + if empty then + minetest.chat_send_player(player,"none:") + end + end + },false) +end + factions.register_command("who", { description = "List players in your faction, and their ranks.", global_privileges = {"faction_user"}, @@ -505,7 +776,7 @@ factions.register_command("setspawn", { },false) factions.register_command("where", { - description = "See whose parcel your standing on.", + description = "See whose parcel you stand on.", infaction = false, global_privileges = {"faction_user"}, on_success = function(player, faction, pos, parcelpos, args) @@ -543,7 +814,7 @@ factions.register_command("spawn", { },false) factions.register_command("promote", { - description = "Promotes a player to a new rank.", + description = "Promotes a player to a rank", format = {"player", "string"}, faction_permissions = {"promote"}, global_privileges = {"faction_user"}, @@ -567,22 +838,7 @@ factions.register_command("power", { return true end },false) ---[[ -factions.register_command("setbanner", { - description = "Sets the banner you're on as the faction's banner.", - faction_permissions = {"banner"}, - on_success = function(player, faction, pos, parcelpos, args) - local meta = minetest.get_meta({x = pos.x, y = pos.y - 1, z = pos.z}) - local banner = meta:get_string("banner") - if not banner then - minetest.chat_send_player(player, "No banner found.") - return false - end - faction:set_banner(banner) - end -},false) ---]] ---[[ + factions.register_command("convert", { description = "Load factions in the old format", infaction = false, @@ -597,7 +853,7 @@ factions.register_command("convert", { return true end },false) ---]] + factions.register_command("free", { description = "Forcefully frees a parcel", infaction = false, diff --git a/config.lua b/config.lua index 4f65e67..03b52e7 100644 --- a/config.lua +++ b/config.lua @@ -1,28 +1,36 @@ -------------------------------------------------------------------------------- --- factions Mod by Sapier --- --- License WTFPL --- ---! @file config.lua ---! @brief settings file ---! @copyright Coder12a ---! @author Coder12a ---! @date 2018-03-13 --- --- Contact sapier a t gmx net -------------------------------------------------------------------------------- +factions_config = {} -config = {} -config.protection_max_depth = tonumber(minetest.setting_get("protection_max_depth")) or -512 -config.power_per_parcel = tonumber(minetest.setting_get("power_per_parcel")) or 0.5 -config.power_per_death = tonumber(minetest.setting_get("power_per_death")) or 0.25 -config.power_per_tick = tonumber(minetest.setting_get("power_per_tick")) or 0.125 -config.tick_time = tonumber(minetest.setting_get("tick_time")) or 60 -config.power_per_attack = tonumber(minetest.setting_get("power_per_attack")) or 10 -config.faction_name_max_length = tonumber(minetest.setting_get("faction_name_max_length")) or 50 -config.rank_name_max_length = tonumber(minetest.setting_get("rank_name_max_length")) or 25 -config.maximum_faction_inactivity = tonumber(minetest.setting_get("maximum_faction_inactivity")) or 604800 -config.power = tonumber(minetest.setting_get("power")) or 2 -config.maxpower = tonumber(minetest.setting_get("maxpower")) or 2 -config.power_per_banner = tonumber(minetest.setting_get("power_per_banner")) or 10. -config.attack_parcel = minetest.settings:get_bool("attack_parcel") or false \ No newline at end of file +factions_config.protection_max_depth = tonumber(minetest.setting_get("protection_max_depth")) or -512 +factions_config.power_per_parcel = tonumber(minetest.setting_get("power_per_parcel")) or 0.5 +factions_config.power_per_death = tonumber(minetest.setting_get("power_per_death")) or 0.25 +factions_config.power_per_tick = tonumber(minetest.setting_get("power_per_tick")) or 0.125 +factions_config.tick_time = tonumber(minetest.setting_get("tick_time")) or 60 +factions_config.power_per_attack = tonumber(minetest.setting_get("power_per_attack")) or 10 +factions_config.faction_name_max_length = tonumber(minetest.setting_get("faction_name_max_length")) or 50 +factions_config.rank_name_max_length = tonumber(minetest.setting_get("rank_name_max_length")) or 25 +factions_config.maximum_faction_inactivity = tonumber(minetest.setting_get("maximum_faction_inactivity")) or 604800 +factions_config.maximum_parcelless_faction_time = tonumber(minetest.setting_get("maximum_parcelless_faction_time")) or 10800 +factions_config.power = tonumber(minetest.setting_get("power")) or 0 +factions_config.maxpower = tonumber(minetest.setting_get("maxpower")) or 0 +factions_config.power_per_player = tonumber(minetest.setting_get("power_per_player")) or 2. +factions_config.enable_power_per_player = minetest.settings:get_bool("power_per_playerb") or true +factions_config.attack_parcel = minetest.settings:get_bool("attack_parcel") or false +factions_config.faction_diplomacy = minetest.settings:get_bool("faction_diplomacy") or true +--[[ +factions_config.protection_max_depth = -512 +factions_config.power_per_parcel = 0.5 +factions_config.power_per_death = 0.25 +factions_config.power_per_tick = 0.125 +factions_config.tick_time = 60 +factions_config.power_per_attack = 10 +factions_config.faction_name_max_length = 50 +factions_config.rank_name_max_length = 25 +factions_config.maximum_faction_inactivity = 604800 +factions_config.maximum_parcelless_faction_time = 10800 +factions_config.power = 0 +factions_config.maxpower = 0 +factions_config.power_per_player = 2 +factions_config.enable_power_per_player = true +factions_config.attack_parcel = false +factions_config.faction_diplomacy = true +--]] \ No newline at end of file diff --git a/factions.lua b/factions.lua index b6a5feb..424e841 100644 --- a/factions.lua +++ b/factions.lua @@ -1,17 +1,3 @@ -------------------------------------------------------------------------------- --- factions Mod by Sapier --- --- License WTFPL --- ---! @file factions.lua ---! @brief factions core file ---! @copyright Sapier, agrecascino, shamoanjac, Coder12a ---! @author Sapier, agrecascino, shamoanjac, Coder12a ---! @date 2016-08-12 --- --- Contact sapier a t gmx net -------------------------------------------------------------------------------- - --read some basic information local factions_worldid = minetest.get_worldpath() @@ -27,15 +13,26 @@ factions.players = {} factions.factions = {} --- settings -factions.protection_max_depth = config.protection_max_depth -factions.power_per_parcel = config.power_per_parcel -factions.power_per_death = config.power_per_death -factions.power_per_tick = config.power_per_tick -factions.tick_time = config.tick_time -factions.power_per_attack = config.power_per_attack -factions.faction_name_max_length = config.faction_name_max_length -factions.rank_name_max_length = config.rank_name_max_length -factions.maximum_faction_inactivity = config.maximum_faction_inactivity +factions.protection_max_depth = factions_config.protection_max_depth +factions.power_per_parcel = factions_config.power_per_parcel +factions.power_per_death = factions_config.power_per_death +factions.power_per_tick = factions_config.power_per_tick +factions.tick_time = factions_config.tick_time +factions.power_per_attack = factions_config.power_per_attack +factions.faction_name_max_length = factions_config.faction_name_max_length +factions.rank_name_max_length = factions_config.rank_name_max_length +factions.maximum_faction_inactivity = factions_config.maximum_faction_inactivity +factions.maximum_parcelless_faction_time = factions_config.maximum_parcelless_faction_time +factions.attack_parcel = factions_config.attack_parcel +factions.faction_diplomacy = factions_config.faction_diplomacy +factions.power_per_player = factions_config.power_per_player +factions.enable_power_per_player = factions_config.enable_power_per_player +factions.power = factions_config.power +factions.maxpower = factions_config.maxpower +factions.attack_parcel = factions_config.attack_parcel + +-- clear mem. +factions_config = nil --------------------- --! @brief returns whether a faction can be created or not (allows for implementation of blacklists and the like) @@ -71,23 +68,27 @@ factions.Faction.__index = factions.Faction -- description: set the faction's description -- ranks: create and delete ranks -- spawn: set the faction's spawn --- banner: set the faction's banner -- promote: set a player's rank +-- diplomacy: make war, or an alliance with other teams. -factions.permissions = {"disband", "claim", "playerslist", "build", "description", "ranks", "spawn", "banner", "promote"} +factions.permissions = {"disband", "claim", "playerslist", "build", "description", "ranks", "spawn", "promote"} + +if factions.faction_diplomacy then + table.insert(factions.permissions,"diplomacy") +end function factions.Faction:new(faction) faction = { --! @brief power of a faction (needed for parcel claiming) - power = config.power, + power = factions.power, --! @brief maximum power of a faction - maxpower = config.maxpower, + maxpower = factions.maxpower, --! @brief power currently in use usedpower = 0., --! @brief list of player names players = {}, --! @brief table of ranks/permissions - ranks = {["leader"] = {"disband", "claim", "playerslist", "build", "description", "ranks", "spawn", "banner", "promote"}, + ranks = {["leader"] = factions.permissions, ["moderator"] = {"claim", "playerslist", "build", "spawn"}, ["member"] = {"build"} }, @@ -105,18 +106,22 @@ function factions.Faction:new(faction) land = {}, --! @brief table of allies allies = {}, + -- + request_inbox = {}, --! @brief table of enemies enemies = {}, + --! + at_peace_with = {}, --! @brief table of parcels/factions that are under attack attacked_parcels = {}, --! @brief whether faction is closed or open (boolean) join_free = false, - --! @brief banner texture string - banner = "bg_white.png", --! @brief gives certain privileges is_admin = false, --! @brief last time anyone logged on last_logon = os.time(), + --! @brief how long this has been without parcels + no_parcel = os.time(), } or faction setmetatable(faction, self) return faction @@ -231,11 +236,29 @@ function factions.Faction.count_land(self) return count end +minetest.register_on_prejoinplayer(function(name, ip) + factions_ip.player_ips[name] = ip +end) + function factions.Faction.add_player(self, player, rank) self:on_player_join(player) self.players[player] = rank or self.default_rank factions.players[player] = self.name self.invited_players[player] = nil + if factions.enable_power_per_player then + local ip = factions_ip.player_ips[player] + local notsame = true + for i,k in pairs(self.players) do + local other_ip = factions_ip.player_ips[k] + if other_ip == ip then + notsame = false + break + end + end + if notsame then + self:increase_maxpower(factions.power_per_player) + end + end local playerslist = minetest.get_connected_players() for i in pairs(playerslist) do local realplayer = playerslist[i] @@ -260,12 +283,26 @@ function factions.Faction.remove_player(self, player) factions.players[player] = nil self:on_player_leave(player) self:check_players_in_faction(self) + if factions.enable_power_per_player then + local ip = factions_ip.player_ips[player] + local notsame = true + for i,k in pairs(self.players) do + local other_ip = factions_ip.player_ips[k] + if other_ip == ip then + notsame = false + break + end + end + if notsame then + self:decrease_maxpower(factions.power_per_player) + end + end local playerslist = minetest.get_connected_players() for i in pairs(playerslist) do local realplayer = playerslist[i] if realplayer:get_player_name() == player then - removeHud(realplayer,"1") - removeHud(realplayer,"2") + removeHud(realplayer,"factionName") + removeHud(realplayer,"powerWatch") end end factions.save() @@ -276,7 +313,7 @@ end function factions.Faction.can_claim_parcel(self, parcelpos) local fac = factions.parcels[parcelpos] if fac then - if factions.factions[fac].power < 0. and self.power >= factions.power_per_parcel then + if factions.factions[fac].power < 0. and self.power >= factions.power_per_parcel and not self.allies[factions.factions[fac].name] and not self.at_peace_with[factions.factions[fac].name] then return true else return false @@ -294,12 +331,14 @@ function factions.Faction.claim_parcel(self, parcelpos) if otherfac then local faction = factions.factions[otherfac] faction:unclaim_parcel(parcelpos) + faction:parcelless_check() end factions.parcels[parcelpos] = self.name self.land[parcelpos] = true self:decrease_power(factions.power_per_parcel) self:increase_usedpower(factions.power_per_parcel) self:on_claim_parcel(parcelpos) + self:parcelless_check() factions.save() end @@ -310,12 +349,44 @@ function factions.Faction.unclaim_parcel(self, parcelpos) self:increase_power(factions.power_per_parcel) self:decrease_usedpower(factions.power_per_parcel) self:on_unclaim_parcel(parcelpos) + self:parcelless_check() factions.save() end +function factions.Faction.parcelless_check(self) + if self.land then + local count = 0 + for index, value in pairs(self.land) do + count = count + 1 + end + if count > 0 then + if self.no_parcel ~= -1 then + self:broadcast("Faction " .. self.name .. " will not be disbanded because it now has parcels.") + end + self.no_parcel = -1 + else + self.no_parcel = os.time() + self:broadcast("Faction " .. self.name .. " will disband in " .. factions.maximum_parcelless_faction_time .. " seconds because it has no parcels.") + end + end +end + --! @brief disband faction, updates global players and parcels table function factions.Faction.disband(self, reason) local playerslist = minetest.get_connected_players() + for i,v in pairs(factions.factions) do + if v.name ~= self.name then + if v.enemies[self.name] then + v:end_enemy(self.name) + end + if v.allies[self.name] then + v:end_alliance(self.name) + end + if v.at_peace_with[self.name] then + v:end_peace(self.name) + end + end + end for k, _ in pairs(factions.players) do -- remove players affiliation factions.players[k] = nil end @@ -328,8 +399,8 @@ function factions.Faction.disband(self, reason) local realplayer = playerslist[i] local faction = factions.get_player_faction(realplayer:get_player_name()) if not faction then - removeHud(realplayer,"1") - removeHud(realplayer,"2") + removeHud(realplayer,"factionName") + removeHud(realplayer,"powerWatch") end end factions.save() @@ -397,6 +468,9 @@ function factions.Faction.new_alliance(self, faction) self:on_new_alliance(faction) if self.enemies[faction] then self:end_enemy(faction) + end + if self.at_peace_with[faction] then + self:end_peace(faction) end factions.save() end @@ -405,11 +479,30 @@ function factions.Faction.end_alliance(self, faction) self:on_end_alliance(faction) factions.save() end +function factions.Faction.new_peace(self, faction) + self.at_peace_with[faction] = true + self:on_new_peace(faction) + if self.allies[faction] then + self:end_alliance(faction) + end + if self.enemies[faction] then + self:end_enemy(faction) + end + factions.save() +end +function factions.Faction.end_peace(self, faction) + self.at_peace_with[faction] = nil + self:on_end_peace(faction) + factions.save() +end function factions.Faction.new_enemy(self, faction) self.enemies[faction] = true self:on_new_enemy(faction) if self.allies[faction] then self:end_alliance(faction) + end + if self.at_peace_with[faction] then + self:end_peace(faction) end factions.save() end @@ -449,12 +542,6 @@ function factions.Faction.delete_rank(self, rank, newrank) factions.save() end ---! @param newbanner texture string of the new banner -function factions.Faction.set_banner(self, newbanner) - self.banner = newbanner - self:on_new_banner() -end - --! @brief set a player's rank function factions.Faction.promote(self, member, rank) self.players[member] = rank @@ -484,20 +571,24 @@ function factions.Faction.is_online(self) end function factions.Faction.attack_parcel(self, parcelpos) - if config.attack_parcel then + if factions.attack_parcel then local attacked_faction = factions.get_parcel_faction(parcelpos) if attacked_faction then - self.power = self.power - factions.power_per_attack - if attacked_faction.attacked_parcels[parcelpos] then - attacked_faction.attacked_parcels[parcelpos][self.name] = true + if not self.allies[attacked_faction.name] then + self.power = self.power - factions.power_per_attack + if attacked_faction.attacked_parcels[parcelpos] then + attacked_faction.attacked_parcels[parcelpos][self.name] = true + else + attacked_faction.attacked_parcels[parcelpos] = {[self.name] = true} + end + attacked_faction:broadcast("Parcel ("..parcelpos..") is being attacked by "..self.name.."!!") + if self.power < 0. then -- punish memers + minetest.chat_send_all("Faction "..self.name.." has attacked too much and has now negative power!") + end + factions.save() else - attacked_faction.attacked_parcels[parcelpos] = {[self.name] = true} + self:broadcast("You can not attack that parcel because it belongs to an ally.") end - attacked_faction:broadcast("Parcel ("..parcelpos..") is being attacked by "..self.name.."!!") - if self.power < 0. then -- punish memers - minetest.chat_send_all("Faction "..self.name.." has attacked too much and has now negative power!") - end - factions.save() end end end @@ -581,6 +672,22 @@ function factions.Faction.on_end_alliance(self, faction) self:broadcast("This faction is no longer allied with "..faction.."!") end +function factions.Faction.on_new_peace(self, faction) + self:broadcast("This faction is now at peace with "..faction) +end + +function factions.Faction.on_end_peace(self, faction) + self:broadcast("This faction is no longer at peace with "..faction.."!") +end + +function factions.Faction.on_new_enemy(self, faction) + self:broadcast("This faction is now at war with "..faction) +end + +function factions.Faction.on_end_enemy(self, faction) + self:broadcast("This faction is no longer at war with "..faction.."!") +end + function factions.Faction.on_set_spawn(self) self:broadcast("The faction spawn has been set to ("..util.coords3D_string(self.spawn)..").") end @@ -593,10 +700,6 @@ function factions.Faction.on_delete_rank(self, rank, newrank) self:broadcast("The rank "..rank.." has been deleted and replaced by "..newrank) end -function factions.Faction.on_new_banner(self) - self:broadcast("A new banner has been set.") -end - function factions.Faction.on_promote(self, member) minetest.chat_send_player(member, "You have been promoted to "..self.players[member]) end @@ -702,7 +805,8 @@ function factions.save() else minetest.log("error","MOD factions: unable to save factions world specific data!: " .. error) end - + factions_ip.save() + end ------------------------------------------------------------------------------- @@ -749,9 +853,13 @@ function factions.load() if not faction.last_logon then faction.last_logon = os.time() end + if not faction.no_parcel then + faction.no_parcel = os.time() + end end file:close() end + factions_ip.load() end function factions.convert(filename) @@ -806,104 +914,31 @@ factions.faction_tick = function() local now = os.time() for facname, faction in pairs(factions.factions) do if faction:is_online() then + if factions.enable_power_per_player then + local playerslist = minetest.get_connected_players() + for i in pairs(playerslist) do + local faction_name = factions.get_player_faction(playerslist[i]) + if facname == faction_name then + increase_power(power_per_tick) + end + end + end faction:increase_power(factions.power_per_tick) end if now - faction.last_logon > factions.maximum_faction_inactivity then faction:disband() + else + if faction.no_parcel ~= -1 and now - faction.no_parcel > factions.maximum_parcelless_faction_time then + faction:disband() + end end end end -hud_ids = {} - -createHudFactionName = function(player,factionname) - local name = player:get_player_name() - local id_name = name .. "1" - if not hud_ids[id_name] then - hud_ids[id_name] = player:hud_add({ - hud_elem_type = "text", - name = "factionName", - number = 0xFFFFFF, - position = {x=1, y = 0}, - text = "Faction "..factionname, - scale = {x=1, y=1}, - alignment = {x=-1, y=0}, - offset = {x = -20, y = 20} - }) - end -end - -createHudPower = function(player,faction) - local name = player:get_player_name() - local id_name = name .. "2" - if not hud_ids[id_name] then - hud_ids[id_name] = player:hud_add({ - hud_elem_type = "text", - name = "powerWatch", - number = 0xFFFFFF, - position = {x=0.9, y = .98}, - text = "Power "..faction.power.."/"..faction.maxpower - faction.usedpower.."/"..faction.maxpower, - scale = {x=1, y=1}, - alignment = {x=-1, y=0}, - offset = {x = 0, y = 0} - }) - end -end - -updateHudPower = function(player,faction) - local name = player:get_player_name() - local id_name = name .. "2" - if hud_ids[id_name] then - player:hud_change(hud_ids[id_name],"text","Power "..faction.power.."/"..faction.maxpower - faction.usedpower.."/"..faction.maxpower) - end -end - -removeHud = function(player,numberString) - local name = player:get_player_name() - local id_name = name .. numberString - if hud_ids[id_name] then - player:hud_remove(hud_ids[id_name]) - hud_ids[id_name] = nil - end -end - -hudUpdate = function() - minetest.after(.5, - function() - local playerslist = minetest.get_connected_players() - for i in pairs(playerslist) do - local player = playerslist[i] - local name = player:get_player_name() - local faction = factions.get_faction_at(player:getpos()) - local id_name = name .. "0" - if hud_ids[id_name] then - player:hud_change(hud_ids[id_name],"text",(faction and faction.name) or "Wilderness") - end - end - hudUpdate() - end) -end - -factionUpdate = function() - minetest.after(factions.tick_time, - function() - factions.faction_tick() - factionUpdate() - end) -end - minetest.register_on_joinplayer( function(player) local name = player:get_player_name() - hud_ids[name .. "0"] = player:hud_add({ - hud_elem_type = "text", - name = "factionLand", - number = 0xFFFFFF, - position = {x=0.1, y = .98}, - text = "Wilderness", - scale = {x=1, y=1}, - alignment = {x=0, y=0}, - }) + createHudfactionLand(player) local faction = factions.get_player_faction(name) if faction then faction.last_logon = os.time() @@ -915,14 +950,9 @@ end minetest.register_on_leaveplayer( function(player) - local name = player:get_player_name() - local id_name = name .. "0" - if hud_ids[id_name] then - player:hud_remove(hud_ids[id_name]) - hud_ids[id_name] = nil - end - removeHud(player,"1") - removeHud(player,"2") + removeHud(player,"factionLand") + removeHud(player,"factionName") + removeHud(player,"powerWatch") end ) @@ -975,22 +1005,15 @@ minetest.is_protected = function(pos, player) elseif player_faction then if parcel_faction.name == player_faction.name then return not parcel_faction:has_permission(player, "build") - else - return not parcel_faction:parcel_is_attacked_by(parcelpos, player_faction) + elseif parcel_faction.allies[player_faction.name] then + return not player_faction:has_permission(player, "build") + else + return not parcel_faction:parcel_is_attacked_by(parcelpos, player_faction) end else return true end end -function grant_new_player_faction_user_priv(player) - local name = player.name - local privs = minetest.get_player_privs(name) - privs.faction_user = true - minetest.set_player_privs(name, privs) -end - -register_on_newplayer(grant_new_player_faction_user_priv) - hudUpdate() factionUpdate() \ No newline at end of file diff --git a/hud.lua b/hud.lua new file mode 100644 index 0000000..1f51923 --- /dev/null +++ b/hud.lua @@ -0,0 +1,90 @@ +hud_ids = {} + +createHudfactionLand = function(player) + local name = player:get_player_name() + hud_ids[name .. "factionLand"] = player:hud_add({ + hud_elem_type = "text", + name = "factionLand", + number = 0xFFFFFF, + position = {x=0.1, y = .98}, + text = "Wilderness", + scale = {x=1, y=1}, + alignment = {x=0, y=0}, + }) +end + +createHudFactionName = function(player,factionname) + local name = player:get_player_name() + local id_name = name .. "factionName" + if not hud_ids[id_name] then + hud_ids[id_name] = player:hud_add({ + hud_elem_type = "text", + name = "factionName", + number = 0xFFFFFF, + position = {x=1, y = 0}, + text = "Faction "..factionname, + scale = {x=1, y=1}, + alignment = {x=-1, y=0}, + offset = {x = -20, y = 20} + }) + end +end + +createHudPower = function(player,faction) + local name = player:get_player_name() + local id_name = name .. "powerWatch" + if not hud_ids[id_name] then + hud_ids[id_name] = player:hud_add({ + hud_elem_type = "text", + name = "powerWatch", + number = 0xFFFFFF, + position = {x=0.9, y = .98}, + text = "Power "..faction.power.."/"..faction.maxpower - faction.usedpower.."/"..faction.maxpower, + scale = {x=1, y=1}, + alignment = {x=-1, y=0}, + offset = {x = 0, y = 0} + }) + end +end + +updateHudPower = function(player,faction) + local name = player:get_player_name() + local id_name = name .. "powerWatch" + if hud_ids[id_name] then + player:hud_change(hud_ids[id_name],"text","Power "..faction.power.."/"..faction.maxpower - faction.usedpower.."/"..faction.maxpower) + end +end + +removeHud = function(player,hudname) + local name = player:get_player_name() + local id_name = name .. hudname + if hud_ids[id_name] then + player:hud_remove(hud_ids[id_name]) + hud_ids[id_name] = nil + end +end + +hudUpdate = function() + minetest.after(3, + function() + local playerslist = minetest.get_connected_players() + for i in pairs(playerslist) do + local player = playerslist[i] + local name = player:get_player_name() + local faction = factions.get_faction_at(player:getpos()) + local id_name = name .. "factionLand" + if hud_ids[id_name] then + player:hud_change(hud_ids[id_name],"text",(faction and faction.name) or "Wilderness") + end + end + hudUpdate() + end) +end + +factionUpdate = function() + minetest.after(factions.tick_time, + function() + factions.faction_tick() + factionUpdate() + end) +end \ No newline at end of file diff --git a/init.lua b/init.lua index 64a3d32..639a10a 100644 --- a/init.lua +++ b/init.lua @@ -1,17 +1,3 @@ -------------------------------------------------------------------------------- --- factions Mod by Sapier --- --- License WTFPL --- ---! @file init.lua ---! @brief factions mod to be used by other mods ---! @copyright Sapier, Coder12a ---! @author Sapier, Coder12a ---! @date 2013-05-08 ---! --- Contact sapier a t gmx net -------------------------------------------------------------------------------- - factions_version = "0.8.1" core.log("action", "MOD: factions (by sapier) loading ...") @@ -20,6 +6,8 @@ core.log("action", "MOD: factions (by sapier) loading ...") factions_modpath = minetest.get_modpath("factions") dofile (factions_modpath .. "/config.lua") +dofile (factions_modpath .. "/hud.lua") +dofile (factions_modpath .. "/ip.lua") dofile (factions_modpath .. "/factions.lua") dofile (factions_modpath .. "/chatcommands.lua") dofile (factions_modpath .. "/nodes.lua") diff --git a/ip.lua b/ip.lua new file mode 100644 index 0000000..5ace21c --- /dev/null +++ b/ip.lua @@ -0,0 +1,28 @@ +factions_ip = {} +factions_ip.player_ips = {} + +--read some basic information +local factions_worldid = minetest.get_worldpath() + +function factions_ip.save() + local file,error = io.open(factions_worldid .. "/" .. "factions_iplist.conf","w") + + if file ~= nil then + file:write(minetest.serialize(factions_ip.player_ips)) + file:close() + else + minetest.log("error","MOD factions: unable to save faction player ips!: " .. error) + end +end + +function factions_ip.load() + local file,error = io.open(factions_worldid .. "/" .. "factions_iplist.conf","r") + + if file ~= nil then + local raw_data = file:read("*a") + factions_ip.player_ips = minetest.deserialize(raw_data) + file:close() + else + minetest.log("error","MOD factions: unable to load faction player ips!: " .. error) + end +end \ No newline at end of file diff --git a/nodes.lua b/nodes.lua index 872ae9f..2c17062 100644 --- a/nodes.lua +++ b/nodes.lua @@ -21,7 +21,7 @@ function factions.can_use_chest(pos, player) if not parcel_faction then return true end - return player_faction and (parcel_faction.name == player_faction.name) + return player_faction and (parcel_faction.name == player_faction.name or parcel_faction.allies[player_faction.name]) end minetest.register_node("factions:chest", { diff --git a/settingtypes.txt b/settingtypes.txt index f68ebbf..e82b504 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -18,14 +18,20 @@ faction_name_max_length (Faction name max) int 50 rank_name_max_length (Rank name max length) int 25 # The maximum amount of inactivity before disbanning a faction. maximum_faction_inactivity (Maximum faction inactivity) int 604800 +# The maximum amount of time for a parcelless faction to disban. +maximum_parcelless_faction_time (Maximum parcelless faction time) int 10800 # Power of a starting faction (needed for parcel claiming). power (Starting power) float 2 # Maximum power of a faction. maxpower (Maximum power) float 2 -# How much power the banners make. -power_per_banner (power-per-banner) float 10 +# How much power the players make. +power_per_player (power-per-player) float 10 [BoolSettings] +# Enable or disabled power-per-player. +power_per_playerb (Enable power-per-player) bool true # Enable or disabled attack_parcel function. -attack_parcel (Enable attack parcel) bool false \ No newline at end of file +attack_parcel (Enable attack parcel) bool false +# Enable or disabled faction diplomacy. +faction_diplomacy (Enable faction diplomacy) bool false \ No newline at end of file