2016-07-30 07:38:52 +02:00
--read some basic information
2016-08-07 19:31:11 +02:00
local factions_worldid = minetest.get_worldpath ( )
2016-07-30 07:38:52 +02:00
2016-08-07 19:31:11 +02:00
--! @class factions
--! @brief main class for factions
factions = { }
2016-07-30 07:38:52 +02:00
--! @brief runtime data
2016-08-07 19:31:11 +02:00
factions.factions = { }
2016-08-14 15:53:40 +02:00
factions.parcels = { }
2016-08-07 19:31:11 +02:00
factions.players = { }
2016-07-30 07:38:52 +02:00
2016-08-07 02:11:17 +02:00
---------------------
--! @brief returns whether a faction can be created or not (allows for implementation of blacklists and the like)
2016-08-12 11:16:43 +02:00
--! @param name String containing the faction's name
2016-08-07 19:31:11 +02:00
factions.can_create_faction = function ( name )
2018-10-18 04:04:46 +02:00
if # name > factions_config.faction_name_max_length then
2016-08-18 15:26:19 +02:00
return false
elseif factions.factions [ name ] then
2016-08-07 02:11:17 +02:00
return false
else
return true
2016-08-07 19:36:56 +02:00
end
2016-08-07 02:11:17 +02:00
end
2016-08-08 03:30:29 +02:00
factions.Faction = {
}
2016-08-09 23:00:53 +02:00
util = {
coords3D_string = function ( coords )
return coords.x .. " , " .. coords.y .. " , " .. coords.z
end
}
2016-08-08 03:30:29 +02:00
factions.Faction . __index = factions.Faction
2018-10-31 22:15:08 +01:00
starting_ranks = { [ " leader " ] = { " build " , " door " , " container " , " name " , " description " , " motd " , " invite " , " kick "
, " title " , " set_spawn " , " unset_spawn " , " with_draw " , " territory " , " claim " , " access " , " disband " , " flags " , " create_ranks " , " edit_ranks " , " delete_ranks " , " set_def_ranks " , " reset_ranks " , " promote " } ,
[ " moderator " ] = { " claim " , " door " , " build " , " set_spawn " , " invite " , " kick " , " promote " } ,
[ " member " ] = { " build " , " container " , " door " }
}
2016-08-12 11:16:43 +02:00
-- Faction permissions:
--
-- build: dig and place nodes
2018-10-31 22:15:08 +01:00
-- pain_build: dig and place nodes but take damage doing so
-- door: open/close or dig doors
-- container: be able to use containers like chest
-- name: set the faction's name
-- description: Set the faction description
-- motd: set the faction's message of the day
-- invite: (un)invite players to join the faction
-- kick: kick players off the faction
-- title: set territory titles
-- set_spawn: set the faction's spawn
-- unset_spawn: delete the faction's spawn
-- with_draw: withdraw money from the faction's bank
-- spawn: be able to teleport to the faction's spawn
-- territory: claim or unclaim territory
-- claim: (un)claim parcels of land
-- access: manage access to territory and parcels of land to players or factions
-- disband: disband the faction
-- flags: manage faction's flags
-- create_ranks: create new ranks
-- edit_ranks: edit rank name and permissions
-- delete_ranks: delete ranks
-- set_def_ranks: set the default rank given to new players
-- reset_ranks: reset the ranks back to the default ones
2016-08-12 11:16:43 +02:00
-- promote: set a player's rank
2018-10-31 22:15:08 +01:00
-- declare_war: be able to declare war with another faction
-- neutral: be able to send a neutral request to another faction
-- alliance: be able to send a alliance request to another faction and break alliance treaties too
-- accept_treaty: be able to accept a treaty request from another faction
-- refuse_treaty: be able to refuse a treaty request from another faction
factions.permissions = { " build " , " pain_build " , " door " , " container " , " name " , " description " , " motd " , " invite " , " kick "
, " title " , " set_spawn " , " unset_spawn " , " with_draw " , " territory " , " claim " , " access " , " disband " , " flags " , " create_ranks " , " edit_ranks " , " delete_ranks " , " set_def_ranks " , " reset_ranks " , " promote " }
factions.permissions_desc = { " dig and place nodes " , " dig and place nodes but take damage doing so " , " open/close or dig " , " be able to use containers like chest " , " set the faction's name "
, " Set the faction description " , " set the faction's message of the day " , " (un)invite players to join the faction " , " kick players off the faction " , " set territory titles " , " set the faction's spawn "
, " delete the faction's spawn " , " withdraw money from the faction's bank " , " claim or unclaim territory " , " (un)claim parcels of land " , " manage access to territory and parcels of land to players or factions "
, " disband the faction " , " manage faction's flags " , " create new ranks " , " edit rank permissions " , " delete ranks " , " set the default rank given to new players " , " reset the ranks back to the default ones " , " set a player's rank " }
-- open: can the faction be joined without an invite?
-- monsters: can monsters spawn on your land?
-- tax_kick: will players be kicked for not paying tax?
-- animals: can animals spawn on your land?
factions.flags = { " open " , " monsters " , " tax_kick " , " animals " }
factions.flags_desc = { " can the faction be joined without an invite? " , " can monsters spawn on your land?(unused) " , " will players be kicked for not paying tax?(unused) " , " can animals spawn on your land?(unused) " }
if factions_config.faction_diplomacy == true then
table.insert ( factions.permissions , " declare_war " )
table.insert ( factions.permissions , " neutral " )
table.insert ( factions.permissions , " alliance " )
table.insert ( factions.permissions , " accept_treaty " )
table.insert ( factions.permissions , " refuse_treaty " )
table.insert ( factions.permissions_desc , " be able to declare war with another faction " )
table.insert ( factions.permissions_desc , " be able to send a neutral request to another faction " )
table.insert ( factions.permissions_desc , " be able to send a alliance request to another faction and break alliance treaties too " )
table.insert ( factions.permissions_desc , " be able to accept a treaty request from another faction " )
table.insert ( factions.permissions_desc , " be able to refuse a treaty request from another faction " )
local lt = starting_ranks [ " leader " ]
table.insert ( lt , " declare_war " )
table.insert ( lt , " neutral " )
table.insert ( lt , " alliance " )
table.insert ( lt , " accept_treaty " )
table.insert ( lt , " refuse_treaty " )
starting_ranks [ " leader " ] = lt
end
2018-10-15 17:24:58 +02:00
2018-10-31 22:15:08 +01:00
if factions_config.spawn_teleport == true then
table.insert ( factions.permissions , " spawn " )
table.insert ( factions.permissions_desc , " be able to teleport to the faction's spawn " )
table.insert ( starting_ranks [ " leader " ] , " spawn " )
table.insert ( starting_ranks [ " moderator " ] , " spawn " )
table.insert ( starting_ranks [ " member " ] , " spawn " )
2018-10-15 17:24:58 +02:00
end
2018-10-12 19:41:55 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction : new ( faction )
faction = {
2018-10-31 22:15:08 +01:00
name = " " ,
2016-08-14 15:53:40 +02:00
--! @brief power of a faction (needed for parcel claiming)
2018-10-18 04:04:46 +02:00
power = factions_config.power ,
2016-08-12 11:16:43 +02:00
--! @brief maximum power of a faction
2018-10-18 04:04:46 +02:00
maxpower = factions_config.maxpower ,
2016-08-16 15:44:19 +02:00
--! @brief power currently in use
usedpower = 0. ,
2016-08-12 11:16:43 +02:00
--! @brief list of player names
2016-08-07 02:11:17 +02:00
players = { } ,
2018-10-17 04:58:15 +02:00
--! @brief list of player names online
onlineplayers = { } ,
--! @brief list of player names offline
offlineplayers = { } ,
2016-08-12 11:16:43 +02:00
--! @brief table of ranks/permissions
2018-10-31 22:15:08 +01:00
ranks = starting_ranks ,
2016-08-12 11:16:43 +02:00
--! @brief name of the leader
2016-08-07 02:11:17 +02:00
leader = nil ,
2018-10-31 22:15:08 +01:00
--! @brief spawn of the faction
spawn = { x = 0 , y = 0 , z = 0 } ,
2016-08-12 11:16:43 +02:00
--! @brief default joining rank for new members
2016-08-07 02:11:17 +02:00
default_rank = " member " ,
2016-08-12 11:16:43 +02:00
--! @brief default rank assigned to the leader
2016-08-07 02:11:17 +02:00
default_leader_rank = " leader " ,
2016-08-12 11:16:43 +02:00
--! @brief faction's description string
2016-08-07 02:11:17 +02:00
description = " Default faction description. " ,
2018-10-25 07:21:42 +02:00
--! @brief faction's message of the day.
message_of_the_day = " " ,
2016-08-12 11:16:43 +02:00
--! @brief list of players currently invited (can join with /f join)
2016-08-07 02:11:17 +02:00
invited_players = { } ,
2016-08-14 15:53:40 +02:00
--! @brief table of claimed parcels (keys are parcelpos strings)
2016-08-07 02:11:17 +02:00
land = { } ,
2016-08-12 11:16:43 +02:00
--! @brief table of allies
2016-08-07 02:11:17 +02:00
allies = { } ,
2018-10-15 17:24:58 +02:00
--
request_inbox = { } ,
2016-08-12 11:16:43 +02:00
--! @brief table of enemies
2016-08-07 02:11:17 +02:00
enemies = { } ,
2018-10-15 17:24:58 +02:00
--!
2018-10-18 07:15:26 +02:00
neutral = { } ,
2016-08-14 15:53:40 +02:00
--! @brief table of parcels/factions that are under attack
attacked_parcels = { } ,
2016-08-12 11:16:43 +02:00
--! @brief whether faction is closed or open (boolean)
2018-10-31 22:15:08 +01:00
join_free = false ,
2016-08-17 22:28:12 +02:00
--! @brief gives certain privileges
2016-08-20 00:12:40 +02:00
is_admin = false ,
2018-10-30 01:16:39 +01:00
--! @brief if a player on the faction has a nil rank
rankless = false ,
2016-08-20 00:12:40 +02:00
--! @brief last time anyone logged on
last_logon = os.time ( ) ,
2018-10-15 17:24:58 +02:00
--! @brief how long this has been without parcels
no_parcel = os.time ( ) ,
2016-08-08 03:30:29 +02:00
} or faction
setmetatable ( faction , self )
return faction
end
2016-08-07 02:11:17 +02:00
2016-08-08 03:30:29 +02:00
2016-08-12 11:16:43 +02:00
--! @brief create a new empty faction
2018-10-31 22:15:08 +01:00
function factions . new_faction ( name , do_not_save )
2018-10-23 05:21:32 +02:00
local faction = factions.Faction : new ( nil )
2016-08-08 03:30:29 +02:00
faction.name = name
2016-08-07 19:36:56 +02:00
factions.factions [ name ] = faction
2016-08-15 00:47:31 +02:00
faction : on_create ( )
2018-10-18 04:31:07 +02:00
minetest.after ( 1 ,
function ( f )
f : on_no_parcel ( )
end , faction )
2018-10-31 22:15:08 +01:00
if not do_not_save then
factions.save ( )
end
2016-08-07 02:11:17 +02:00
return faction
end
2018-10-23 05:21:32 +02:00
function factions . start_diplomacy ( name , faction )
2018-10-31 22:15:08 +01:00
for i , fac in pairs ( factions.factions ) do
2018-10-23 05:21:32 +02:00
if i ~= name and not ( faction.neutral [ i ] or faction.allies [ i ] or faction.enemies [ i ] ) then
2018-10-29 04:03:55 +01:00
faction : new_enemy ( i )
2018-10-31 22:15:08 +01:00
fac : new_enemy ( name )
2018-10-23 05:21:32 +02:00
end
end
end
2018-10-31 22:15:08 +01:00
function factions . Faction . set_name ( self , name )
local oldname = self.name
local oldfaction = factions.factions [ oldname ]
self.name = name
for i , fac in pairs ( factions.factions ) do
if i ~= oldname then
if fac.neutral [ oldname ] then
fac.neutral [ oldname ] = nil
fac.neutral [ name ] = true
end
if fac.allies [ oldname ] then
fac.allies [ oldname ] = nil
fac.allies [ name ] = true
end
if fac.enemies [ oldname ] then
fac.enemies [ oldname ] = nil
fac.enemies [ name ] = true
end
end
end
for parcel in pairs ( self.land ) do
factions.parcels [ parcel ] = self.name
end
for playername in pairs ( self.players ) do
factions.players [ playername ] = self.name
end
factions.factions [ oldname ] = nil
factions.factions [ name ] = oldfaction
factions.factions [ name ] . name = name
for playername in pairs ( self.onlineplayers ) do
updateFactionName ( playername , name )
end
self : on_set_name ( oldname )
factions.save ( )
end
2016-08-08 03:30:29 +02:00
function factions . Faction . increase_power ( self , power )
self.power = self.power + power
2016-08-16 15:44:19 +02:00
if self.power > self.maxpower - self.usedpower then
self.power = self.maxpower - self.usedpower
2016-08-15 09:54:28 +02:00
end
2018-10-17 04:58:15 +02:00
for i in pairs ( self.onlineplayers ) do
updateHudPower ( minetest.get_player_by_name ( i ) , self )
2018-10-12 19:41:55 +02:00
end
2016-08-08 03:30:29 +02:00
factions.save ( )
end
function factions . Faction . decrease_power ( self , power )
self.power = self.power - power
2018-10-17 04:58:15 +02:00
for i in pairs ( self.onlineplayers ) do
updateHudPower ( minetest.get_player_by_name ( i ) , self )
2018-10-12 19:41:55 +02:00
end
2016-08-08 03:30:29 +02:00
factions.save ( )
end
2016-08-15 10:16:12 +02:00
function factions . Faction . increase_maxpower ( self , power )
self.maxpower = self.maxpower + power
2018-10-17 04:58:15 +02:00
for i in pairs ( self.onlineplayers ) do
updateHudPower ( minetest.get_player_by_name ( i ) , self )
2018-10-12 19:41:55 +02:00
end
2016-08-15 10:16:12 +02:00
factions.save ( )
end
function factions . Faction . decrease_maxpower ( self , power )
self.maxpower = self.maxpower - power
if self.maxpower < 0. then -- should not happen
self.maxpower = 0.
end
2018-10-17 04:58:15 +02:00
for i in pairs ( self.onlineplayers ) do
updateHudPower ( minetest.get_player_by_name ( i ) , self )
2018-10-12 19:41:55 +02:00
end
2016-08-15 10:16:12 +02:00
end
2016-08-16 15:44:19 +02:00
function factions . Faction . increase_usedpower ( self , power )
self.usedpower = self.usedpower + power
2018-10-17 04:58:15 +02:00
for i in pairs ( self.onlineplayers ) do
updateHudPower ( minetest.get_player_by_name ( i ) , self )
2018-10-12 19:41:55 +02:00
end
2016-08-16 15:44:19 +02:00
end
function factions . Faction . decrease_usedpower ( self , power )
self.usedpower = self.usedpower - power
if self.usedpower < 0. then
self.usedpower = 0.
end
2018-10-17 04:58:15 +02:00
for i in pairs ( self.onlineplayers ) do
updateHudPower ( minetest.get_player_by_name ( i ) , self )
2018-10-12 19:41:55 +02:00
end
2016-08-16 15:44:19 +02:00
end
2018-10-23 05:21:32 +02:00
-- power-per-players only.
function factions . Faction . check_power ( self )
if factions_config.enable_power_per_player then
for player , unused in pairs ( self.players ) do
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_config.powermax_per_player )
end
end
end
end
2016-08-16 15:44:19 +02:00
function factions . Faction . count_land ( self )
local count = 0.
for k , v in pairs ( self.land ) do
count = count + 1
end
return count
end
2018-10-15 17:24:58 +02:00
minetest.register_on_prejoinplayer ( function ( name , ip )
factions_ip.player_ips [ name ] = ip
end )
2016-08-08 03:30:29 +02:00
function factions . Faction . add_player ( self , player , rank )
2016-08-10 02:46:54 +02:00
self : on_player_join ( player )
2016-08-08 03:30:29 +02:00
self.players [ player ] = rank or self.default_rank
factions.players [ player ] = self.name
self.invited_players [ player ] = nil
2018-10-18 04:04:46 +02:00
if factions_config.enable_power_per_player then
2018-10-15 17:24:58 +02:00
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
2018-10-18 04:04:46 +02:00
self : increase_maxpower ( factions_config.powermax_per_player )
2018-10-15 17:24:58 +02:00
end
end
2018-10-17 04:58:15 +02:00
local pdata = minetest.get_player_by_name ( player )
local ipc = pdata : is_player_connected ( player )
if ipc then
createHudFactionName ( pdata , self.name )
createHudPower ( pdata , self )
self.offlineplayers [ player ] = nil
self.onlineplayers [ player ] = 1
else
self.offlineplayers [ player ] = 1
self.onlineplayers [ player ] = nil
2018-10-12 19:41:55 +02:00
end
2016-08-08 03:30:29 +02:00
factions.save ( )
end
2018-10-12 19:41:55 +02:00
function factions . Faction . check_players_in_faction ( self )
2018-10-27 17:51:39 +02:00
for i , k in pairs ( self.players ) do
return true
2018-10-12 19:41:55 +02:00
end
2018-10-27 17:51:39 +02:00
self : disband ( " Zero players on faction. " )
return false
2018-10-12 19:41:55 +02:00
end
2016-08-08 03:30:29 +02:00
function factions . Faction . remove_player ( self , player )
self.players [ player ] = nil
factions.players [ player ] = nil
self : on_player_leave ( player )
2018-10-12 19:41:55 +02:00
self : check_players_in_faction ( self )
2018-10-18 04:04:46 +02:00
if factions_config.enable_power_per_player then
2018-10-15 17:24:58 +02:00
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
2018-10-18 04:04:46 +02:00
self : decrease_maxpower ( factions_config.powermax_per_player )
2018-10-15 17:24:58 +02:00
end
end
2018-10-17 04:58:15 +02:00
local pdata = minetest.get_player_by_name ( player )
local ipc = pdata : is_player_connected ( player )
if ipc then
removeHud ( pdata , " factionName " )
removeHud ( pdata , " powerWatch " )
2018-10-12 19:41:55 +02:00
end
2018-10-17 04:58:15 +02:00
self.offlineplayers [ player ] = nil
self.onlineplayers [ player ] = nil
2016-08-08 03:30:29 +02:00
factions.save ( )
end
2016-08-14 15:53:40 +02:00
--! @param parcelpos position of the wanted parcel
--! @return whether this faction can claim a parcelpos
function factions . Faction . can_claim_parcel ( self , parcelpos )
local fac = factions.parcels [ parcelpos ]
2016-08-09 04:39:40 +02:00
if fac then
2018-10-18 07:15:26 +02:00
if factions.factions [ fac ] . power < 0. and self.power >= factions_config.power_per_parcel and not self.allies [ factions.factions [ fac ] . name ] and not self.neutral [ factions.factions [ fac ] . name ] then
2016-08-09 04:39:40 +02:00
return true
else
return false
end
2018-10-18 04:04:46 +02:00
elseif self.power < factions_config.power_per_parcel then
2016-08-08 16:31:11 +02:00
return false
end
return true
end
2016-08-14 15:53:40 +02:00
--! @brief claim a parcel, update power and update global parcels table
function factions . Faction . claim_parcel ( self , parcelpos )
2016-08-09 04:39:40 +02:00
-- check if claiming over other faction's territory
2016-08-14 15:53:40 +02:00
local otherfac = factions.parcels [ parcelpos ]
2016-08-09 04:39:40 +02:00
if otherfac then
local faction = factions.factions [ otherfac ]
2016-08-14 15:53:40 +02:00
faction : unclaim_parcel ( parcelpos )
2018-10-15 17:24:58 +02:00
faction : parcelless_check ( )
2016-08-09 04:39:40 +02:00
end
2016-08-14 15:53:40 +02:00
factions.parcels [ parcelpos ] = self.name
self.land [ parcelpos ] = true
2018-10-18 04:04:46 +02:00
self : decrease_power ( factions_config.power_per_parcel )
self : increase_usedpower ( factions_config.power_per_parcel )
2016-08-14 15:53:40 +02:00
self : on_claim_parcel ( parcelpos )
2018-10-15 17:24:58 +02:00
self : parcelless_check ( )
2016-08-08 03:30:29 +02:00
factions.save ( )
end
2016-08-14 15:43:53 +02:00
2016-08-14 15:53:40 +02:00
--! @brief claim a parcel, update power and update global parcels table
function factions . Faction . unclaim_parcel ( self , parcelpos )
factions.parcels [ parcelpos ] = nil
self.land [ parcelpos ] = nil
2018-10-18 04:04:46 +02:00
self : increase_power ( factions_config.power_per_parcel )
self : decrease_usedpower ( factions_config.power_per_parcel )
2016-08-14 15:53:40 +02:00
self : on_unclaim_parcel ( parcelpos )
2018-10-15 17:24:58 +02:00
self : parcelless_check ( )
2016-08-08 03:30:29 +02:00
factions.save ( )
end
2016-08-12 11:16:43 +02:00
2018-10-15 17:24:58 +02:00
function factions . Faction . parcelless_check ( self )
if self.land then
local count = 0
for index , value in pairs ( self.land ) do
count = count + 1
2018-10-23 06:03:11 +02:00
break
2018-10-15 17:24:58 +02:00
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 ( )
2018-10-18 04:31:07 +02:00
self : on_no_parcel ( )
2018-10-15 17:24:58 +02:00
end
end
end
2016-08-14 15:53:40 +02:00
--! @brief disband faction, updates global players and parcels table
2016-08-20 00:15:45 +02:00
function factions . Faction . disband ( self , reason )
2018-10-28 05:14:52 +01:00
if not self.is_admin then
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.neutral [ self.name ] then
v : end_neutral ( self.name )
end
2018-10-15 17:24:58 +02:00
end
end
2018-10-28 05:14:52 +01:00
for k , _ in pairs ( self.players ) do -- remove players affiliation
factions.players [ k ] = nil
end
for k , v in pairs ( self.land ) do -- remove parcel claims
factions.parcels [ k ] = nil
end
self : on_disband ( reason )
2018-10-31 22:15:08 +01:00
for i , l in pairs ( self.onlineplayers ) do
2018-10-28 05:14:52 +01:00
removeHud ( i , " factionName " )
removeHud ( i , " powerWatch " )
end
factions.factions [ self.name ] = nil
factions.save ( )
2018-10-15 17:24:58 +02:00
end
2016-08-08 03:30:29 +02:00
end
2016-08-12 11:16:43 +02:00
--! @brief change the faction leader
2016-08-08 03:30:29 +02:00
function factions . Faction . set_leader ( self , player )
2016-08-27 22:34:09 +02:00
if self.leader then
self.players [ self.leader ] = self.default_rank
end
2016-08-08 03:30:29 +02:00
self.leader = player
self.players [ player ] = self.default_leader_rank
self : on_new_leader ( )
factions.save ( )
end
2016-08-12 11:16:43 +02:00
2018-10-25 07:21:42 +02:00
function factions . Faction . set_message_of_the_day ( self , text )
self.message_of_the_day = text
factions.save ( )
end
2016-08-12 11:16:43 +02:00
--! @brief check permissions for a given player
--! @return boolean indicating permissions. Players not in faction always receive false
2016-08-08 03:30:29 +02:00
function factions . Faction . has_permission ( self , player , permission )
local p = self.players [ player ]
if not p then
return false
end
local perms = self.ranks [ p ]
2018-10-27 21:01:49 +02:00
if perms then
for i in ipairs ( perms ) do
if perms [ i ] == permission then
return true
end
end
2018-10-30 01:36:46 +01:00
else
2018-10-31 15:41:34 +01:00
if not self.rankless then
self.rankless = true
factions.save ( )
end
2018-10-27 21:01:49 +02:00
end
2016-08-08 03:30:29 +02:00
return false
end
2018-10-22 21:30:11 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . set_description ( self , new )
self.description = new
self : on_change_description ( )
factions.save ( )
end
2016-08-12 11:16:43 +02:00
--! @brief places player in invite list
2016-08-08 03:30:29 +02:00
function factions . Faction . invite_player ( self , player )
self.invited_players [ player ] = true
self : on_player_invited ( player )
factions.save ( )
end
2016-08-12 11:16:43 +02:00
--! @brief removes player from invite list (can no longer join via /f join)
2016-08-08 03:30:29 +02:00
function factions . Faction . revoke_invite ( self , player )
self.invited_players [ player ] = nil
self : on_revoke_invite ( player )
factions.save ( )
end
2016-08-12 11:16:43 +02:00
--! @brief set faction openness
2016-08-08 03:30:29 +02:00
function factions . Faction . toggle_join_free ( self , bool )
self.join_free = bool
self : on_toggle_join_free ( )
factions.save ( )
end
2016-08-12 11:16:43 +02:00
--! @return true if a player can use /f join, false otherwise
2016-08-08 03:30:29 +02:00
function factions . Faction . can_join ( self , player )
return self.join_free or self.invited_players [ player ]
end
2016-08-12 11:16:43 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . new_alliance ( self , faction )
self.allies [ faction ] = true
self : on_new_alliance ( faction )
if self.enemies [ faction ] then
self : end_enemy ( faction )
2018-10-15 17:24:58 +02:00
end
2018-10-18 07:15:26 +02:00
if self.neutral [ faction ] then
self : end_neutral ( faction )
2016-08-08 03:30:29 +02:00
end
factions.save ( )
end
2018-10-22 21:30:11 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . end_alliance ( self , faction )
self.allies [ faction ] = nil
self : on_end_alliance ( faction )
factions.save ( )
end
2018-10-22 21:30:11 +02:00
2018-10-18 07:15:26 +02:00
function factions . Faction . new_neutral ( self , faction )
self.neutral [ faction ] = true
self : on_new_neutral ( faction )
2018-10-15 17:24:58 +02:00
if self.allies [ faction ] then
self : end_alliance ( faction )
end
if self.enemies [ faction ] then
self : end_enemy ( faction )
end
factions.save ( )
end
2018-10-22 21:30:11 +02:00
2018-10-18 07:15:26 +02:00
function factions . Faction . end_neutral ( self , faction )
self.neutral [ faction ] = nil
self : on_end_neutral ( faction )
2018-10-15 17:24:58 +02:00
factions.save ( )
end
2018-10-22 21:30:11 +02:00
2016-08-08 03:30:29 +02:00
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 )
2018-10-15 17:24:58 +02:00
end
2018-10-18 07:15:26 +02:00
if self.neutral [ faction ] then
self : end_neutral ( faction )
2016-08-08 03:30:29 +02:00
end
factions.save ( )
end
2018-10-22 21:30:11 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . end_enemy ( self , faction )
self.enemies [ faction ] = nil
self : on_end_enemy ( faction )
factions.save ( )
end
2016-08-12 11:16:43 +02:00
--! @brief faction's member will now spawn in a new place
2016-08-08 03:30:29 +02:00
function factions . Faction . set_spawn ( self , pos )
2016-08-08 16:31:11 +02:00
self.spawn = { x = pos.x , y = pos.y , z = pos.z }
2016-08-15 01:50:13 +02:00
self : on_set_spawn ( )
2016-08-08 03:30:29 +02:00
factions.save ( )
end
2016-08-12 11:16:43 +02:00
2018-10-31 22:15:08 +01:00
function factions . Faction . tp_spawn ( self , playername )
player = minetest.get_player_by_name ( playername )
if player then
player : moveto ( self.spawn , false )
end
end
2016-08-12 11:16:43 +02:00
--! @brief create a new rank with permissions
--! @param rank the name of the new rank
--! @param rank a list with the permissions of the new rank
2016-08-08 03:30:29 +02:00
function factions . Faction . add_rank ( self , rank , perms )
self.ranks [ rank ] = perms
2016-08-08 16:31:11 +02:00
self : on_add_rank ( rank )
2016-08-08 03:30:29 +02:00
factions.save ( )
end
2016-08-12 11:16:43 +02:00
2018-10-31 22:15:08 +01:00
--! @brief replace an rank's permissions
--! @param rank the name of the rank to edit
--! @param add or remove permissions to the rank
function factions . Faction . replace_privs ( self , rank , perms )
self.ranks [ rank ] = perms
self : on_replace_privs ( rank )
factions.save ( )
end
function factions . Faction . remove_privs ( self , rank , perms )
local revoked = false
local p = self.ranks [ rank ]
for index , perm in pairs ( p ) do
if table_Contains ( perms , perm ) then
revoked = true
table.remove ( p , index )
end
end
self.ranks [ rank ] = p
if revoked then
self : on_remove_privs ( rank , perms )
else
self : broadcast ( " No privilege was revoked from rank " .. rank .. " . " )
end
factions.save ( )
end
function factions . Faction . add_privs ( self , rank , perms )
local added = false
local p = self.ranks [ rank ]
for index , perm in pairs ( perms ) do
if not table_Contains ( p , perm ) then
added = true
table.insert ( p , perm )
end
end
self.ranks [ rank ] = p
if added then
self : on_add_privs ( rank , perms )
else
self : broadcast ( " The rank " .. rank .. " already has these privileges. " )
end
factions.save ( )
end
function factions . Faction . set_rank_name ( self , oldrank , newrank )
local copyrank = self.ranks [ oldrank ]
self.ranks [ newrank ] = copyrank
self.ranks [ oldrank ] = nil
for player , r in pairs ( self.players ) do
if r == oldrank then
self.players [ player ] = newrank
end
end
if oldrank == self.default_leader_rank then
self.default_leader_rank = newrank
self : broadcast ( " The default leader rank has been set to " .. newrank )
end
if oldrank == self.default_rank then
self.default_rank = newrank
self : broadcast ( " The default rank given to new players is set to " .. newrank )
end
self : on_set_rank_name ( oldrank , newrank )
factions.save ( )
end
function factions . Faction . set_def_rank ( self , rank )
2018-10-30 01:36:46 +01:00
for player , r in pairs ( self.players ) do
if r == rank or r == nil or not self.ranks [ r ] then
self.players [ player ] = rank
end
end
self.default_rank = rank
2018-10-31 22:15:08 +01:00
self : on_set_def_rank ( rank )
self.rankless = false
factions.save ( )
end
function factions . Faction . reset_ranks ( self )
self.ranks = starting_ranks
self.default_rank = " member "
self.default_leader_rank_rank = " leader "
for player , r in pairs ( self.players ) do
if not player == leader and ( r == nil or not self.ranks [ r ] ) then
self.players [ player ] = self.default_rank
elseif player == leader then
self.players [ player ] = self.default_leader_rank_rank
end
end
self : on_reset_ranks ( )
self.rankless = false
2018-10-30 01:36:46 +01:00
factions.save ( )
end
2016-08-12 11:16:43 +02:00
--! @brief delete a rank and replace it
--! @param rank the name of the rank to be deleted
--! @param newrank the rank given to players who were previously "rank"
2016-08-08 03:30:29 +02:00
function factions . Faction . delete_rank ( self , rank , newrank )
for player , r in pairs ( self.players ) do
if r == rank then
self.players [ player ] = newrank
end
end
self.ranks [ rank ] = nil
self : on_delete_rank ( rank , newrank )
2018-10-27 20:40:37 +02:00
if rank == self.default_leader_rank then
self.default_leader_rank = newrank
self : broadcast ( " The default leader rank has been set to " .. newrank )
end
if rank == self.default_rank then
self.default_rank = newrank
self : broadcast ( " The default rank given to new players is set to " .. newrank )
end
2016-08-08 03:30:29 +02:00
factions.save ( )
end
2016-08-14 15:43:53 +02:00
2016-08-12 11:16:43 +02:00
--! @brief set a player's rank
2016-08-08 23:25:31 +02:00
function factions . Faction . promote ( self , member , rank )
self.players [ member ] = rank
self : on_promote ( member )
end
2016-08-14 15:43:53 +02:00
2016-08-12 11:16:43 +02:00
--! @brief send a message to all members
2016-08-09 23:00:53 +02:00
function factions . Faction . broadcast ( self , msg , sender )
2016-08-10 01:54:18 +02:00
local message = self.name .. " > " .. msg
2016-08-09 23:00:53 +02:00
if sender then
message = sender .. " @ " .. message
end
2016-08-10 01:54:18 +02:00
message = " Faction< " .. message
2018-10-18 04:36:07 +02:00
for k , _ in pairs ( self.onlineplayers ) do
2016-08-09 23:00:53 +02:00
minetest.chat_send_player ( k , message )
end
end
2016-08-08 21:09:10 +02:00
2016-08-15 09:54:28 +02:00
--! @brief checks whether a faction has at least one connected player
function factions . Faction . is_online ( self )
2018-10-18 04:36:07 +02:00
for playername , _ in pairs ( self.onlineplayers ) do
2016-08-15 09:54:28 +02:00
if minetest.get_player_by_name ( playername ) then
return true
end
end
return false
end
2016-08-15 18:31:11 +02:00
function factions . Faction . attack_parcel ( self , parcelpos )
2018-10-18 04:04:46 +02:00
if factions_config.attack_parcel then
2018-10-12 19:41:55 +02:00
local attacked_faction = factions.get_parcel_faction ( parcelpos )
if attacked_faction then
2018-10-15 17:24:58 +02:00
if not self.allies [ attacked_faction.name ] then
2018-10-18 04:04:46 +02:00
self.power = self.power - factions_config.power_per_attack
2018-10-15 17:24:58 +02:00
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 ( )
2018-10-12 19:41:55 +02:00
else
2018-10-15 17:24:58 +02:00
self : broadcast ( " You can not attack that parcel because it belongs to an ally. " )
2018-10-12 19:41:55 +02:00
end
end
end
2016-08-15 18:31:11 +02:00
end
function factions . Faction . stop_attack ( self , parcelpos )
local attacked_faction = factions.parcels [ parcelpos ]
if attacked_faction then
attacked_faction = factions.factions [ attacked_faction ]
if attacked_faction.attacked_parcels [ parcelpos ] then
attacked_faction.attacked_parcels [ parcelpos ] [ self.name ] = nil
2016-08-15 23:52:12 +02:00
attacked_faction : broadcast ( " Parcel ( " .. parcelpos .. " ) is no longer under attack from " .. self.name .. " . " )
self : broadcast ( " Parcel ( " .. parcelpos .. " ) has been reconquered by " .. attacked_faction.name .. " . " )
2016-08-15 18:31:11 +02:00
end
factions.save ( )
end
end
2016-08-19 10:02:12 +02:00
function factions . Faction . parcel_is_attacked_by ( self , parcelpos , faction )
if self.attacked_parcels [ parcelpos ] then
return self.attacked_parcels [ parcelpos ] [ faction.name ]
else
return false
end
end
2016-08-08 03:30:29 +02:00
--------------------------
-- callbacks for events --
function factions . Faction . on_create ( self ) --! @brief called when the faction is added to the global faction list
2016-08-10 02:46:54 +02:00
minetest.chat_send_all ( " Faction " .. self.name .. " has been created. " )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2018-10-31 22:15:08 +01:00
function factions . Faction . on_set_name ( self , oldname )
minetest.chat_send_all ( " Faction " .. oldname .. " has been changed its name to " .. self.name .. " . " )
end
2018-10-18 04:31:07 +02:00
function factions . Faction . on_no_parcel ( self )
local now = os.time ( ) - self.no_parcel
local l = factions_config.maximum_parcelless_faction_time
self : broadcast ( " This faction will disband in " .. l - now .. " seconds, because it has no parcels. " )
end
2016-08-08 03:30:29 +02:00
function factions . Faction . on_player_leave ( self , player )
2016-08-09 23:00:53 +02:00
self : broadcast ( player .. " has left this faction. " )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . on_player_join ( self , player )
2016-08-09 23:00:53 +02:00
self : broadcast ( player .. " has joined this faction. " )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-14 15:53:40 +02:00
function factions . Faction . on_claim_parcel ( self , pos )
2016-08-14 23:27:51 +02:00
self : broadcast ( " Parcel ( " .. pos .. " ) has been claimed. " )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-14 15:53:40 +02:00
function factions . Faction . on_unclaim_parcel ( self , pos )
2016-08-14 23:27:51 +02:00
self : broadcast ( " Parcel ( " .. pos .. " ) has been unclaimed. " )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-20 00:15:45 +02:00
function factions . Faction . on_disband ( self , reason )
local msg = " Faction " .. self.name .. " has been disbanded. "
if reason then
msg = msg .. " ( " .. reason .. " ) "
end
minetest.chat_send_all ( msg )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . on_new_leader ( self )
2016-08-09 23:00:53 +02:00
self : broadcast ( self.leader .. " is now the leader of this faction. " )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . on_change_description ( self )
2016-08-09 23:00:53 +02:00
self : broadcast ( " Faction description has been modified to: " .. self.description )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . on_player_invited ( self , player )
2016-08-09 23:00:53 +02:00
minetest.chat_send_player ( player , " You have been invited to faction " .. self.name )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . on_toggle_join_free ( self , player )
2016-08-29 01:41:23 +02:00
if self.join_free then
self : broadcast ( " This faction is now invite-free. " )
else
self : broadcast ( " This faction is no longer invite-free. " )
end
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . on_new_alliance ( self , faction )
2016-08-09 23:00:53 +02:00
self : broadcast ( " This faction is now allied with " .. faction )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . on_end_alliance ( self , faction )
2016-08-09 23:00:53 +02:00
self : broadcast ( " This faction is no longer allied with " .. faction .. " ! " )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2018-10-18 07:15:26 +02:00
function factions . Faction . on_new_neutral ( self , faction )
self : broadcast ( " This faction is now neutral with " .. faction )
2018-10-15 17:24:58 +02:00
end
2018-10-18 07:15:26 +02:00
function factions . Faction . on_end_neutral ( self , faction )
self : broadcast ( " This faction is no longer neutral with " .. faction .. " ! " )
2018-10-15 17:24:58 +02:00
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
2016-08-08 03:30:29 +02:00
function factions . Faction . on_set_spawn ( self )
2016-08-15 01:50:13 +02:00
self : broadcast ( " The faction spawn has been set to ( " .. util.coords3D_string ( self.spawn ) .. " ). " )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-08 03:30:29 +02:00
function factions . Faction . on_add_rank ( self , rank )
2016-08-10 02:43:31 +02:00
self : broadcast ( " The rank " .. rank .. " has been created with privileges: " .. table.concat ( self.ranks [ rank ] , " , " ) )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2018-10-31 22:15:08 +01:00
function factions . Faction . on_replace_privs ( self , rank )
self : broadcast ( " The privileges in rank " .. rank .. " have been delete and changed to: " .. table.concat ( self.ranks [ rank ] , " , " ) )
end
function factions . Faction . on_remove_privs ( self , rank , privs )
self : broadcast ( " The privileges in rank " .. rank .. " have been revoked: " .. table.concat ( privs , " , " ) )
end
function factions . Faction . on_add_privs ( self , rank , privs )
self : broadcast ( " The privileges in rank " .. rank .. " have been added: " .. table.concat ( privs , " , " ) )
end
function factions . Faction . on_set_rank_name ( self , rank , newrank )
self : broadcast ( " The name of rank " .. rank .. " has been changed to " .. newrank )
end
2016-08-08 03:30:29 +02:00
function factions . Faction . on_delete_rank ( self , rank , newrank )
2016-08-09 23:00:53 +02:00
self : broadcast ( " The rank " .. rank .. " has been deleted and replaced by " .. newrank )
2016-08-08 03:30:29 +02:00
end
2016-08-14 15:43:53 +02:00
2018-10-31 22:15:08 +01:00
function factions . Faction . on_set_def_rank ( self , rank )
2018-10-30 01:36:46 +01:00
self : broadcast ( " The default rank given to new players has been changed to " .. rank )
end
2018-10-31 22:15:08 +01:00
function factions . Faction . on_reset_ranks ( self )
self : broadcast ( " All of the faction's ranks have been reset to the default ones. " )
end
2016-08-08 23:25:31 +02:00
function factions . Faction . on_promote ( self , member )
2016-08-15 00:24:30 +02:00
minetest.chat_send_player ( member , " You have been promoted to " .. self.players [ member ] )
2016-08-09 23:00:53 +02:00
end
2016-08-14 15:43:53 +02:00
2016-08-09 23:00:53 +02:00
function factions . Faction . on_revoke_invite ( self , player )
minetest.chat_send_player ( player , " You are no longer invited to faction " .. self.name )
2016-08-08 23:25:31 +02:00
end
2016-08-08 03:30:29 +02:00
2016-08-14 15:53:40 +02:00
function factions . get_parcel_pos ( pos )
2018-10-18 04:40:00 +02:00
if factions_config.protection_style == " 2d " then
2018-10-18 04:04:46 +02:00
return math.floor ( pos.x / factions_config.parcel_size ) .. " , " .. math.floor ( pos.z / factions_config.parcel_size )
2018-10-18 04:40:00 +02:00
elseif factions_config.protection_style == " 3d " then
2018-10-18 04:04:46 +02:00
return math.floor ( pos.x / factions_config.parcel_size ) .. " , " .. math.floor ( pos.y / factions_config.parcel_size ) .. " , " .. math.floor ( pos.z / factions_config.parcel_size )
2018-10-17 04:58:15 +02:00
end
2016-08-07 19:36:56 +02:00
end
2016-07-30 07:38:52 +02:00
2016-08-18 12:46:21 +02:00
function factions . get_player_faction ( playername )
2016-08-17 22:28:12 +02:00
local facname = factions.players [ playername ]
if facname then
local faction = factions.factions [ facname ]
return faction
end
return nil
end
function factions . get_parcel_faction ( parcelpos )
2016-08-18 12:46:21 +02:00
local facname = factions.parcels [ parcelpos ]
2016-08-17 22:28:12 +02:00
if facname then
local faction = factions.factions [ facname ]
return faction
end
return nil
end
function factions . get_faction ( facname )
return factions.factions [ facname ]
end
function factions . get_faction_at ( pos )
2018-10-17 04:58:15 +02:00
local y = pos.y
2018-10-18 04:04:46 +02:00
if factions_config.protection_depth_height_limit and ( pos.y < factions_config.protection_max_depth or pos.y > factions_config.protection_max_height ) then
2018-10-17 04:58:15 +02:00
return nil
end
2016-08-17 22:28:12 +02:00
local parcelpos = factions.get_parcel_pos ( pos )
return factions.get_parcel_faction ( parcelpos )
end
2016-07-30 07:38:52 +02:00
-------------------------------------------------------------------------------
2016-08-07 02:11:17 +02:00
-- name: add_faction(name)
2016-07-30 07:38:52 +02:00
--
2016-08-07 02:11:17 +02:00
--! @brief add a faction
2016-08-07 19:31:11 +02:00
--! @memberof factions
2016-07-30 07:38:52 +02:00
--! @public
--
2016-08-07 02:11:17 +02:00
--! @param name of faction to add
2016-07-30 07:38:52 +02:00
--!
2016-08-07 02:11:17 +02:00
--! @return faction object/false (succesfully added faction or not)
2016-07-30 07:38:52 +02:00
-------------------------------------------------------------------------------
2016-08-07 19:31:11 +02:00
function factions . add_faction ( name )
2016-08-07 19:36:56 +02:00
if factions.can_create_faction ( name ) then
local fac = factions.new_faction ( name )
fac : on_create ( )
return fac
else
return nil
end
2016-07-30 07:38:52 +02:00
end
-------------------------------------------------------------------------------
-- name: get_faction_list()
--
2016-08-07 19:31:11 +02:00
--! @brief get list of factions
--! @memberof factions
2016-07-30 07:38:52 +02:00
--! @public
--!
2016-08-07 19:31:11 +02:00
--! @return list of factions
2016-07-30 07:38:52 +02:00
-------------------------------------------------------------------------------
2016-08-07 19:31:11 +02:00
function factions . get_faction_list ( )
2016-07-30 07:38:52 +02:00
2016-08-18 15:21:59 +02:00
local retval = { }
for key , value in pairs ( factions.factions ) do
table.insert ( retval , key )
end
return retval
2016-07-30 07:38:52 +02:00
end
-------------------------------------------------------------------------------
-- name: save()
--
--! @brief save data to file
2016-08-07 19:31:11 +02:00
--! @memberof factions
2016-07-30 07:38:52 +02:00
--! @private
-------------------------------------------------------------------------------
2016-08-07 19:31:11 +02:00
function factions . save ( )
2016-07-30 07:38:52 +02:00
2016-08-18 15:21:59 +02:00
--saving is done much more often than reading data to avoid delay
--due to figuring out which data to save and which is temporary only
--all data is saved here
--this implies data needs to be cleant up on load
local file , error = io.open ( factions_worldid .. " / " .. " factions.conf " , " w " )
if file ~= nil then
file : write ( minetest.serialize ( factions.factions ) )
file : close ( )
else
minetest.log ( " error " , " MOD factions: unable to save factions world specific data!: " .. error )
end
2018-10-15 17:24:58 +02:00
factions_ip.save ( )
2016-07-30 07:38:52 +02:00
end
-------------------------------------------------------------------------------
-- name: load()
--
--! @brief load data from file
2016-08-07 19:31:11 +02:00
--! @memberof factions
2016-07-30 07:38:52 +02:00
--! @private
--
--! @return true/false
-------------------------------------------------------------------------------
2016-08-07 19:31:11 +02:00
function factions . load ( )
2018-10-23 05:21:32 +02:00
local filename = " factions.conf "
local file , error = io.open ( factions_worldid .. " / " .. filename , " r " )
2016-08-18 15:21:59 +02:00
if file ~= nil then
local raw_data = file : read ( " *a " )
2018-10-28 05:49:28 +01:00
local current_version = misc_mod_data.data . factions_version
misc_mod_data.load ( )
2018-10-28 06:06:44 +01:00
local old_version = misc_mod_data.data . factions_version
2018-10-29 04:03:55 +01:00
local tabledata = minetest.deserialize ( raw_data )
file : close ( )
if tabledata then
factions.factions = tabledata
if current_version ~= old_version or factions.is_old_file ( tabledata ) then
if factions.convert ( filename ) then
minetest.after ( 5 ,
function ( )
minetest.chat_send_all ( " Factions successfully converted. " )
end )
end
2018-10-18 04:55:06 +02:00
end
2018-10-29 04:03:55 +01:00
for facname , faction in pairs ( factions.factions ) do
minetest.log ( " action " , facname .. " , " .. faction.name )
for player , rank in pairs ( faction.players ) do
minetest.log ( " action " , player .. " , " .. rank )
factions.players [ player ] = facname
end
for parcelpos , val in pairs ( faction.land ) do
factions.parcels [ parcelpos ] = facname
end
setmetatable ( faction , factions.Faction )
if not faction.maxpower or faction.maxpower <= 0. then
faction.maxpower = faction.power
if faction.power < 0. then
faction.maxpower = 0.
end
end
if not faction.attacked_parcels then
faction.attacked_parcels = { }
end
if not faction.usedpower then
faction.usedpower = faction : count_land ( ) * factions_config.power_per_parcel
end
if # faction.name > factions_config.faction_name_max_length then
faction : disband ( )
end
if not faction.last_logon then
faction.last_logon = os.time ( )
end
if faction.no_parcel ~= - 1 then
faction.no_parcel = os.time ( )
end
if faction : count_land ( ) > 0 then
faction.no_parcel = - 1
end
2018-10-31 22:15:08 +01:00
faction.onlineplayers = { }
faction.offlineplayers = { }
if faction.players then
for i , _ in pairs ( faction.players ) do
2018-10-29 04:03:55 +01:00
faction.offlineplayers [ i ] = _
end
end
2018-10-17 18:47:53 +02:00
end
2018-10-29 04:03:55 +01:00
misc_mod_data.data . factions_version = current_version
misc_mod_data.save ( )
factions.save ( )
else
minetest.after ( 5 ,
function ( )
minetest.chat_send_all ( " Failed to deserialize saved file. " )
end )
end
2016-08-07 02:11:17 +02:00
end
2018-10-15 17:24:58 +02:00
factions_ip.load ( )
2016-07-30 22:33:10 +02:00
end
2016-08-08 18:51:17 +02:00
2018-10-23 05:21:32 +02:00
function factions . is_old_file ( oldfactions )
local tempfaction = factions.Faction : new ( nil )
local pass = false
for facname , faction in pairs ( oldfactions ) do
for ni , nl in pairs ( tempfaction ) do
pass = false
for key , value in pairs ( faction ) do
if key == ni then
pass = true
break
end
end
if not pass then
tempfaction = nil
return true
end
end
-- Only check one faction to save time.
if not pass then
tempfaction = nil
return true
else
tempfaction = nil
return false
end
end
tempfaction = nil
return false
end
2016-08-08 18:51:17 +02:00
function factions . convert ( filename )
local file , error = io.open ( factions_worldid .. " / " .. filename , " r " )
if not file then
minetest.chat_send_all ( " Cannot load file " .. filename .. " . " .. error )
return false
end
local raw_data = file : read ( " *a " )
2018-10-29 04:03:55 +01:00
file : close ( )
2018-10-31 22:15:08 +01:00
2016-08-08 18:51:17 +02:00
local data = minetest.deserialize ( raw_data )
2018-10-31 22:15:08 +01:00
local old_permissions = { " disband " , " claim " , " playerslist " , " build " , " description " , " ranks " , " spawn " , " promote " , " diplomacy " }
2018-10-23 05:21:32 +02:00
for facname , faction in pairs ( data ) do
2018-10-29 04:03:55 +01:00
local newfac = factions.new_faction ( facname , true )
2018-10-23 05:21:32 +02:00
for oi , ol in pairs ( faction ) do
if newfac [ oi ] then
newfac [ oi ] = ol
end
end
2018-10-29 04:03:55 +01:00
if faction.players then
newfac.players = faction.players
2018-10-23 05:21:32 +02:00
end
2018-10-29 04:03:55 +01:00
if faction.land then
2018-10-31 22:15:08 +01:00
newfac.land = faction.land
2018-10-29 04:03:55 +01:00
end
if faction.ranks then
newfac.ranks = faction.ranks
2018-10-23 05:21:32 +02:00
end
2018-10-31 01:17:28 +01:00
if faction.rankless then
newfac.rankless = faction.rankless
else
newfac.rankless = false
end
2018-10-31 22:15:08 +01:00
for rank , perm in pairs ( faction.ranks ) do
for index , value in pairs ( perm ) do
if value == " playerslist " then
table.remove ( faction.ranks [ rank ] , index )
table.insert ( faction.ranks [ rank ] , " kick " )
table.insert ( faction.ranks [ rank ] , " invite " )
elseif value == " ranks " then
table.remove ( faction.ranks [ rank ] , index )
table.insert ( faction.ranks [ rank ] , " create_ranks " )
table.insert ( faction.ranks [ rank ] , " edit_ranks " )
table.insert ( faction.ranks [ rank ] , " delete_ranks " )
table.insert ( faction.ranks [ rank ] , " set_def_ranks " )
table.insert ( faction.ranks [ rank ] , " reset_ranks " )
elseif value == " diplomacy " then
table.remove ( faction.ranks [ rank ] , index )
table.insert ( faction.ranks [ rank ] , " declare_war " )
table.insert ( faction.ranks [ rank ] , " neutral " )
table.insert ( faction.ranks [ rank ] , " alliance " )
table.insert ( faction.ranks [ rank ] , " accept_treaty " )
table.insert ( faction.ranks [ rank ] , " refuse_treaty " )
elseif value == " spawn " then
if not factions_config.spawn_teleport == true then
table.remove ( faction.ranks [ rank ] , index )
end
table.insert ( faction.ranks [ rank ] , " set_spawn " )
table.insert ( faction.ranks [ rank ] , " unset_spawn " )
end
end
end
2018-10-23 05:21:32 +02:00
factions.start_diplomacy ( facname , newfac )
newfac : check_power ( )
2016-08-08 18:51:17 +02:00
end
2018-10-29 04:03:55 +01:00
-- Create runtime data.
for facname , faction in pairs ( factions.factions ) do
if faction.players then
for player , unused in pairs ( faction.players ) do
factions.players [ player ] = faction.name
end
end
if faction.land then
for l , unused in pairs ( faction.land ) do
factions.parcels [ l ] = facname
end
end
end
2016-08-08 18:51:17 +02:00
return true
end
2016-08-18 15:21:59 +02:00
2016-08-07 02:11:17 +02:00
minetest.register_on_dieplayer (
2016-08-18 15:21:59 +02:00
function ( player )
local faction = factions.get_player_faction ( player : get_player_name ( ) )
if not faction then
2016-08-15 09:54:28 +02:00
return true
2016-08-07 02:11:17 +02:00
end
2018-10-18 04:04:46 +02:00
faction : decrease_power ( factions_config.power_per_death )
2016-08-18 15:21:59 +02:00
return true
end
2016-08-07 02:11:17 +02:00
)
2018-10-17 04:58:15 +02:00
function factions . faction_tick ( )
2016-08-20 00:12:40 +02:00
local now = os.time ( )
2016-08-15 09:54:28 +02:00
for facname , faction in pairs ( factions.factions ) do
if faction : is_online ( ) then
2018-10-18 04:04:46 +02:00
if factions_config.enable_power_per_player then
2018-10-17 04:58:15 +02:00
local t = faction.onlineplayers
local count = 0
for _ in pairs ( t ) do count = count + 1 end
2018-10-18 04:04:46 +02:00
faction : increase_power ( factions_config.power_per_player * count )
2018-10-17 04:58:15 +02:00
else
2018-10-18 04:04:46 +02:00
faction : increase_power ( factions_config.power_per_tick )
2018-10-15 17:24:58 +02:00
end
2016-08-15 09:54:28 +02:00
end
2018-10-18 04:04:46 +02:00
if now - faction.last_logon > factions_config.maximum_faction_inactivity or ( faction.no_parcel ~= - 1 and now - faction.no_parcel > factions_config.maximum_parcelless_faction_time ) then
2016-08-20 00:12:40 +02:00
faction : disband ( )
end
2016-08-15 09:54:28 +02:00
end
end
2018-10-12 19:41:55 +02:00
2016-08-07 02:11:17 +02:00
minetest.register_on_joinplayer (
2016-08-18 15:21:59 +02:00
function ( player )
2018-10-12 19:41:55 +02:00
local name = player : get_player_name ( )
2018-10-28 04:37:49 +01:00
minetest.after ( 5 , createHudfactionLand , player )
2018-10-12 19:41:55 +02:00
local faction = factions.get_player_faction ( name )
2016-08-21 01:15:41 +02:00
if faction then
faction.last_logon = os.time ( )
2018-10-28 04:37:49 +01:00
minetest.after ( 5 , createHudFactionName , player , faction.name )
minetest.after ( 5 , createHudPower , player , faction )
2018-10-17 04:58:15 +02:00
faction.offlineplayers [ name ] = nil
faction.onlineplayers [ name ] = 1
2018-10-18 04:31:07 +02:00
if faction.no_parcel ~= - 1 then
local now = os.time ( ) - faction.no_parcel
local l = factions_config.maximum_parcelless_faction_time
2018-10-23 05:55:19 +02:00
minetest.chat_send_player ( name , " This faction will disband in " .. l - now .. " seconds, because it has no parcels. " )
2018-10-18 04:31:07 +02:00
end
2018-10-31 22:15:08 +01:00
if faction : has_permission ( name , " accept_treaty " ) or faction : has_permission ( name , " refuse_treaty " ) then
2018-10-23 05:55:19 +02:00
for _ in pairs ( faction.request_inbox ) do minetest.chat_send_player ( name , " You have diplomatic requests in the inbox. " ) break end
2018-10-18 07:20:05 +02:00
end
2018-10-30 01:36:46 +01:00
if faction : has_permission ( name , " ranks " ) then
if faction.rankless then
2018-10-31 22:15:08 +01:00
minetest.chat_send_player ( name , " You need to reset the default rank because there are rankless players in this faction. reset all the ranks back to default using /f reset_ranks (You will lose all of your custom ranks) or use /f change_def_rank " )
2018-10-30 01:36:46 +01:00
end
end
2018-10-29 04:03:55 +01:00
if faction.message_of_the_day and ( faction.message_of_the_day ~= " " or faction.message_of_the_day ~= " " ) then
2018-10-25 07:21:42 +02:00
minetest.chat_send_player ( name , faction.message_of_the_day )
end
2016-08-21 01:15:41 +02:00
end
2016-08-18 15:21:59 +02:00
end
2016-08-07 02:11:17 +02:00
)
2018-10-12 19:41:55 +02:00
minetest.register_on_leaveplayer (
function ( player )
2018-10-17 04:58:15 +02:00
local name = player : get_player_name ( )
local faction = factions.get_player_faction ( name )
2018-10-28 02:06:48 +01:00
local id_name1 = name .. " factionLand "
if hud_ids [ id_name1 ] then
hud_ids [ id_name1 ] = nil
end
2018-10-17 04:58:15 +02:00
if faction then
2018-10-28 02:06:48 +01:00
local id_name2 = name .. " factionName "
local id_name3 = name .. " powerWatch "
if hud_ids [ id_name2 ] then
hud_ids [ id_name2 ] = nil
end
if hud_ids [ id_name3 ] then
hud_ids [ id_name3 ] = nil
end
2018-10-17 04:58:15 +02:00
faction.offlineplayers [ name ] = 1
faction.onlineplayers [ name ] = nil
2018-10-31 22:15:08 +01:00
factions.save ( )
2018-10-17 04:58:15 +02:00
end
2018-10-12 19:41:55 +02:00
end
)
2016-08-08 16:31:11 +02:00
minetest.register_on_respawnplayer (
function ( player )
2016-08-18 15:21:59 +02:00
local faction = factions.get_player_faction ( player : get_player_name ( ) )
2016-08-08 16:31:11 +02:00
if not faction then
return false
else
if not faction.spawn then
return false
else
player : setpos ( faction.spawn )
return true
end
end
end
)
2016-08-04 07:21:22 +02:00
2016-08-08 01:10:47 +02:00
2016-08-15 09:54:28 +02:00
2016-08-08 01:10:47 +02:00
local default_is_protected = minetest.is_protected
minetest.is_protected = function ( pos , player )
2018-10-17 04:58:15 +02:00
local y = pos.y
2018-10-18 04:04:46 +02:00
if factions_config.protection_depth_height_limit and ( pos.y < factions_config.protection_max_depth or pos.y > factions_config.protection_max_height ) then
2016-08-15 23:52:12 +02:00
return false
end
2016-08-14 15:53:40 +02:00
local parcelpos = factions.get_parcel_pos ( pos )
2016-08-18 15:21:59 +02:00
local parcel_faction = factions.get_parcel_faction ( parcelpos )
local player_faction = factions.get_player_faction ( player )
2016-08-15 23:52:12 +02:00
-- no faction
2016-08-19 23:10:01 +02:00
if not parcel_faction then
2016-08-08 01:10:47 +02:00
return default_is_protected ( pos , player )
2016-08-19 23:10:01 +02:00
elseif player_faction then
2016-08-19 03:05:44 +02:00
if parcel_faction.name == player_faction.name then
2018-10-31 22:15:08 +01:00
if parcel_faction : has_permission ( player , " pain_build " ) then
local p = minetest.get_player_by_name ( player )
p : set_hp ( p : get_hp ( ) - 0.5 )
end
return not ( parcel_faction : has_permission ( player , " build " ) or parcel_faction : has_permission ( player , " pain_build " ) )
2018-10-15 17:24:58 +02:00
elseif parcel_faction.allies [ player_faction.name ] then
2018-10-31 22:15:08 +01:00
if player_faction : has_permission ( player , " pain_build " ) then
local p = minetest.get_player_by_name ( player )
p : set_hp ( p : get_hp ( ) - 0.5 )
end
return not ( player_faction : has_permission ( player , " build " ) or player_faction : has_permission ( player , " pain_build " ) )
2018-10-15 17:24:58 +02:00
else
return not parcel_faction : parcel_is_attacked_by ( parcelpos , player_faction )
2016-08-15 00:24:30 +02:00
end
2016-08-19 23:10:01 +02:00
else
return true
2016-08-08 01:10:47 +02:00
end
end
2018-10-17 04:58:15 +02:00
function factionUpdate ( )
2018-10-27 22:40:17 +02:00
factions.faction_tick ( )
minetest.after ( factions_config.tick_time , factionUpdate )
2018-10-29 04:48:29 +01:00
end