diff --git a/control.lua b/control.lua index 450eba1e..689da58a 100644 --- a/control.lua +++ b/control.lua @@ -14,7 +14,7 @@ error = function(err) if _G.discord_emit and game then local color = _G.Color and Color.to_hex(defines.text_color.bg) or '0x0' discord_emit{title='SCRIPT ERROR',color=color,description=err} - elseif _G.Game then + elseif _G.Game and game then if Game.print_all(err) == 0 then _error(err) end @@ -32,4 +32,8 @@ ExpLib._unpack_to_G(ExpLib) _G.discord_emit = nil -- un-comment this line if you are not using the json.data -- loads the ExpCore files these are need in order to run the other addons -Ranking, Server, Gui = require('/locale/ExpCore/load'){'Ranking','Server','Gui'} \ No newline at end of file +Ranking, Server, Gui = require('/locale/ExpCore/load'){'Ranking','Server','Gui'} +-- this loads the ranks that Ranking uses +require('/locale/ExpCore/ranks') +-- this loads any edits that are not need in core pcall as file may not be preset +pcall(require,'/locale/Addons/playerRanks') \ No newline at end of file diff --git a/locale/Addons/playerRanks.lua b/locale/Addons/playerRanks.lua new file mode 100644 index 00000000..99d66dc7 --- /dev/null +++ b/locale/Addons/playerRanks.lua @@ -0,0 +1,41 @@ +--[[ +Explosive Gaming + +This file can be used with permission but this and the credit below must remain in the file. +Contact a member of management on our discord to seek permission to use our code. +Any changes that you may make to the code are yours but that does not make the script yours. +Discord: https://discord.gg/r6dC2uK +]] +--Please Only Edit Below This Line----------------------------------------------------------- + +--[[ + How to use groups: +name the name that you can use to refence it. +disallow if present then all ranks in this group will have this added to their disallow. +allow if present then all ranks in this group will have this added to their allow. +highest is asigned by the script to show the highest rank in this group. +lowest is asigned by the script to show the lowest rank in this group. +How to add ranks: +Name is what will be used in the scripts and is often the best choice for display in text. +short_hand is what can be used when short on space but the rank still need to be displayed. +tag is the tag the player will gain when moved to the rank, it can be nil. +time is used for auto-rank feature where you are moved to the rank after a certain play time in minutes. +colour is the RGB value that can be used to emphasise GUI elements based on rank. +power is asigned by the script based on their index in ranks, you can insert new ranks between current ones. +group is asigned by the script to show the group this rank is in +disallow is a list containing input actions that the user can not perform. +allow is a list of custom commands and effects that that rank can use, all defined in the sctips. + +For allow, add the allow as the key and the value as true +Example: test for 'server-interface' => allow['server-interface'] = true + +For disallow, add to the list the end part of the input action +Example: defines.input_action.drop_item -> 'drop_item' +http://lua-api.factorio.com/latest/defines.html#defines.input_action +--]] + +-- see ExpCore/ranks.lua for examples - you add your own and edit pre-made ones here. + +function Ranking._base_preset() + return {} +end \ No newline at end of file diff --git a/locale/ExpCore/commands.lua b/locale/ExpCore/commands.lua index 13cbb2ad..1c9ef779 100644 --- a/locale/ExpCore/commands.lua +++ b/locale/ExpCore/commands.lua @@ -79,7 +79,7 @@ end -- @tparam defines.events.on_console_command event the event rasied by the command= local function run_custom_command(command) local command_data = command_data[command.name] - local player_name = Game.get_player(commnd) and Game.get_player(commnd).name or 'server' + local player_name = Game.get_player(command) and Game.get_player(command).name or 'server' -- is the player allowed to use this command if is_type(Ranking,'table') and is_type(Ranking.get_rank,'function') and not Ranking.get_rank(player_name):allowed(command.name) then player_return{'commands.unauthorized'} diff --git a/locale/ExpCore/load.lua b/locale/ExpCore/load.lua index 4f5b6e25..c7e87a2e 100644 --- a/locale/ExpCore/load.lua +++ b/locale/ExpCore/load.lua @@ -21,7 +21,6 @@ require '/commands' StdExpCoreLib.Server = require '/server' StdExpCoreLib.Gui = {} StdExpCoreLib.Ranking = require '/ranking' -require '/ranks' --[[StdExpCoreLib.Gui = require '/gui' require '/GuiParts/inputs' require '/GuiParts/toolbar' diff --git a/locale/ExpCore/ranking.lua b/locale/ExpCore/ranking.lua index 55a69cd4..9ec4b2c7 100644 --- a/locale/ExpCore/ranking.lua +++ b/locale/ExpCore/ranking.lua @@ -8,37 +8,59 @@ Discord: https://discord.gg/r6dC2uK ]] --Please Only Edit Below This Line----------------------------------------------------------- local Ranking = {} - +Ranking.event = script.generate_event_name() +Ranking._rank = {} +Ranking._group = {} -- this function is to avoid errors - see /ranks.lua -function Ranking._form_links() - return false -end - --- this function is to avoid errors - see /ranks.lua -function Ranking._ranks() +function Ranking._ranks(names) return {} end -- this function is to avoid errors - see /ranks.lua -function Ranking._groups() +function Ranking._groups(names) return {} end +-- this function is to avoid errors - see /ranks.lua +function Ranking._meta() + return {} +end + +-- this function is to avoid errors - see addons/playerRanks.lua +function Ranking._base_preset() + return {} +end + +-- this returns a global list +function Ranking._presets() + if not global.exp_core then global.exp_core = {} end + if not global.exp_core.ranking then global.exp_core.ranking = {meta=Ranking._meta(),old={},current=Ranking._base_preset()} end + return global.exp_core.ranking +end + --- Returns a rank object given a player or rank name -- @usage Ranking.get_rank(game.player) -- Ranking.get_rank('admin') -- @param mixed player|player index|player name|rank name|rank|'server'|'root' what rank to get -- @treturn table the rank that is linked to mixed function Ranking.get_rank(mixed) - local ranks = Ranking._ranks() - return game.players[mixed] and ranks[game.players[mixed].permission_group.name] - or mixed.index and game.players[mixed.index] and ranks[mixed.permission_group.name] - or is_type(mixed,'table') and mixed.group and mixed - or is_type(mixed,'string') and ranks[string.lower(mixed)] and ranks[string.lower(mixed)] - or is_type(mixed,'string') and mixed == 'server' and ranks['root'] - or is_type(mixed,'string') and mixed == 'root' and ranks['root'] - or false - -- ranks[mixed] and ranks[mixed] is to avoid returning nil given any string + if not mixed then return false end + local ranks = Ranking._ranks(true) + local _return = false + if is_type(mixed,'table') then + if mixed.index then + _return = game.players[mixed.index] and ranks[mixed.permission_group.name] or false + else + _return = mixed.group and mixed or false + end + else + _return = game.players[mixed] and ranks[game.players[mixed].permission_group.name] + or table.autokey(ranks,mixed) and table.autokey(ranks,mixed) + or string.contains(mixed,'server') and Ranking.get_group('Root').highest + or string.contains(mixed,'root') and Ranking.get_group('Root').highest + or false + end + return _return end --- Returns the group object used to sort ranks given group name or see Ranking.get_rank @@ -47,11 +69,12 @@ end -- @param mixed player|player index|player name|rank name|rank|'server'|'root'|group name|group what group to get -- @treturn table the group that is linked to mixed function Ranking.get_group(mixed) - local groups = Ranking._groups() + if not mixed then return false end + local groups = Ranking._groups(true) local rank = Ranking.get_rank(mixed) return rank and rank.group or is_type(mixed,'table') and mixed.ranks and mixed - or is_type(mixed,'string') and groups[mixed] and groups[mixed] + or is_type(mixed,'string') and table.autokey(groups,mixed) and table.autokey(groups,mixed) or false end @@ -82,23 +105,23 @@ end -- @param[opt=game.tick] tick the tick that the rank is being given on function Ranking.give_rank(player,rank,by_player,tick) local tick = tick or game.tick - local by_player_name = Game.get_player(by_player).name or game.player and game.player.name or 'server' - local rank = Ranking.get_rank(rank) + local by_player_name = Game.get_player(by_player) and Game.get_player(by_player).name or game.player and game.player.name or 'server' + local rank = Ranking.get_rank(rank) or Ranking.get_rank(Ranking._presets().meta.default) local player = Game.get_player(player) - local old_rank = Ranking.get_rank(player) + local old_rank = Ranking.get_rank(player) or Ranking.get_rank(Ranking._presets().meta.default) local message = 'ranking.rank-down' -- messaging if old_rank.name == rank.name then return end if rank.power < old_rank.power then message = 'ranking.rank-up' end game.print{message,player.name,rank.name,by_player_name} - if not rank.group.name == 'User' then player.print{'ranking.rank-given',rank.name} end - if not player.tag == old_rank.tag then player.print{'ranking.tag-reset'} end + if rank.group.name ~= 'User' then player.print{'ranking.rank-given',rank.name} end + if player.tag ~= old_rank.tag then player.print{'ranking.tag-reset'} end -- rank change player.permission_group = game.permissions.get_group(rank.name) player.tag = rank.tag if not old_rank.group.name == 'Jail' then Ranking._presets().old[player.index] = rank.name end - if Ranking._presets()._event then - script.raise_event(Ranking._presets()._event,{ + if Ranking.event then + script.raise_event(Ranking.event,{ tick=tick, player=player, by_player_name=by_player_name, @@ -117,17 +140,53 @@ function Ranking.revert(player,by_player) Ranking.give_rank(player,Ranking._presets().old[player.index],by_player) end - +--- Given the player has a rank in the preset table it is given +-- @usage Ranking.find_preset(1) +-- @param player the player to test for an auto rank +-- @tparam[opt=nil] tick the tick it happens on +function Ranking.find_preset(player,tick) + local presets = Ranking._presets().current + local meta_data = Ranking._presets().meta + local default = Ranking.get_rank(meta_data.default) + local player = Game.get_player(player) + local current_rank = Ranking.get_rank(player) or {power=-1,group={name='not jail'}} + local ranks = {default} + if current_rank.group.name == 'Jail' then return end + if presets[string.lower(player.name)] then + local rank = Ranking.get_rank(presets[string.lower(player.name)]) + if current_rank.power >= rank.power then return end + table.insert(ranks,rank) + end + if current_rank.power < meta_data.time_highest and tick_to_min(player.online_time) > meta_data.time_lowest then + for _,rank_name in pairs(meta_data.time_ranks) do + local rank = Ranking.get_rank(rank_name) + if tick_to_min(player.online_time) > rank.time then + table.insert(ranks,rank) + end + end + end + local _rank = nil + for _,rank in pairs(ranks) do + if rank.power > current_rank.power then _rank = rank end + end + if _rank then + if _rank.name == default.name then + player.tag = _rank.tag + player.permission_group = game.permissions.get_group(_rank.name) + else + Ranking.give_rank(player,_rank,nil,tick) + end + end +end -- this is the base rank object, do not store in global -Ranking._rank = {} --- Is this rank allowed to open this gui or use this command etc. -- @usage rank:allowed('server-interface') -- @tparam teh action to test for -- @treturn bolean is it allowed function Ranking._rank:allowed(action) - return self.allowed[action] or self.is_root or false + return self.allow[action] or self.is_root or false end --- Get all the players in this rank @@ -169,7 +228,53 @@ function Ranking._rank:print(rtn) end) end end --- this is the base rank object, do not store in global -Ranking._group = {} +-- this is the base group object, do not store in global, these cant be used in game + +-- this makes a new group +-- {name='root',allow={},disallow={}} +function Ranking._group:create(obj) + if game then return end + if not is_type(obj.name,'string') then return end + setmetatable(obj,{__index=Ranking._group}) + obj.ranks = {} + obj.allow = obj.allow or {} + obj.disallow = obj.disallow or {} + Ranking._add_group(obj) + return obj +end + +-- this makes a new rank in side this group +-- {name='Root',short_hand='Root',tag='[Root]',time=nil,colour=defines.colors.white,allow={},disallow={}} +function Ranking._group:add_rank(obj) + if game then return end + if not is_type(obj.name,'string') or + not is_type(obj.short_hand,'string') or + not is_type(obj.tag,'string') or + not is_type(obj.colour,'table') then return end + setmetatable(obj,{__index=Ranking._rank}) + obj.group = self + obj.allow = obj.allow or {} + obj.disallow = obj.disallow or {} + setmetatable(obj.allow,{__index=self.allow}) + setmetatable(obj.disallow,{__index=self.disallow}) + Ranking._add_rank(obj) + Ranking._set_rank_power() + table.insert(self.ranks,obj) + if not self.highest or obj.power > self.highest.power then self.highest = obj end + if not self.lowest or obj.power < self.lowest.power then self.lowest = obj end +end + +Event.register(defines.events.on_player_joined_game,function(event) + Ranking.find_preset(event.player_index) +end) + +Event.register(-1,function(event) + for power,rank in pairs(Ranking._ranks()) do + local perm = game.permissions.create_group(rank.name) + for _,toRemove in pairs(rank.disallow) do + perm.set_allows_action(defines.input_action[toRemove],false) + end + end +end) return Ranking \ No newline at end of file diff --git a/locale/ExpCore/ranks.lua b/locale/ExpCore/ranks.lua index 2fee45a1..a18bbef7 100644 --- a/locale/ExpCore/ranks.lua +++ b/locale/ExpCore/ranks.lua @@ -7,5 +7,126 @@ Any changes that you may make to the code are yours but that does not make the s Discord: https://discord.gg/r6dC2uK ]] --Please Only Edit Below This Line----------------------------------------------------------- +local groups = {} +local ranks = {} -local ranks = {} \ No newline at end of file +function Ranking._add_group(group) if game then return end table.insert(groups,group) end +function Ranking._add_rank(rank) if game then return end table.insert(ranks,rank) end +function Ranking._set_rank_power() if game then return end for power,rank in pairs(ranks) do rank.power = power end end + +--[[ + How to use groups: +name the name that you can use to refence it. +disallow if present then all ranks in this group will have this added to their disallow. +allow if present then all ranks in this group will have this added to their allow. +highest is asigned by the script to show the highest rank in this group. +lowest is asigned by the script to show the lowest rank in this group. +How to add ranks: +Name is what will be used in the scripts and is often the best choice for display in text. +short_hand is what can be used when short on space but the rank still need to be displayed. +tag is the tag the player will gain when moved to the rank, it can be nil. +time is used for auto-rank feature where you are moved to the rank after a certain play time in minutes. +colour is the RGB value that can be used to emphasise GUI elements based on rank. +power is asigned by the script based on their index in ranks, you can insert new ranks between current ones. +group is asigned by the script to show the group this rank is in +disallow is a list containing input actions that the user can not perform. +allow is a list of custom commands and effects that that rank can use, all defined in the sctips. + +For allow, add the allow as the key and the value as true +Example: test for 'server-interface' => allow['server-interface'] = true + +For disallow, add to the list the end part of the input action +Example: defines.input_action.drop_item -> 'drop_item' +http://lua-api.factorio.com/latest/defines.html#defines.input_action +--]] + +-- If you wish to add more groups please use addons/playerRanks.lua +-- If you wish to add to these rank groups use addons/playerRanks.lua +-- DO NOT REMOVE ANY OF THESE GROUPS + +local root = Ranking._group:create{ + name='Root', + allow={ + ['server-interface'] = true + }, + disallow={} +} +local admin = Ranking._group:create{ + name='Admin', + allow={}, + disallow={} +} +local user = Ranking._group:create{ + name='User', + allow={}, + disallow={} +} +local jail = Ranking._group:create{ + name='Jail', + allow={}, + disallow={} +} + +-- If you wish to add more ranks please use addons/playerRanks.lua +-- If you wish to add to these rank use addons/playerRanks.lua +root:add_rank{ + name='Root', + short_hand='Root', + tag='[Root]', + colour=defines.color.white, + is_root=true +} + +user:add_rank{ + name='Guest', + short_hand='', + tag='', + colour={r=255,g=159,b=27}, + is_default=true +} + +-- used to force rank to be read-only +function Ranking._groups(name) + if name then + if name then + local _return = {} + for power,group in pairs(groups) do + _return[group.name] = group + end + return _return + end + end + return groups +end + +function Ranking._ranks(name) + if name then + local _return = {} + for power,rank in pairs(ranks) do + _return[rank.name] = rank + end + return _return + end + return ranks +end + +-- used to save lag by doing some calculation at the start +function Ranking._meta() + local meta = {} + for power,rank in pairs(ranks) do + if rank.is_default then + meta.default = rank.name + end + if rank.is_root then + meta.root = rank.name + end + if rank.time then + table.insert(meta.time_ranks,rank.name) + if not meta.time_highest or power > meta.time_highest then meta.time_highest = power end + if not meta.time_lowest or power < meta.time_lowest then meta.time_lowest = power end + end + meta.time_highest = meta.time_highest or 0 + meta.time_lowest = meta.time_lowest or 0 + end + return meta +end \ No newline at end of file diff --git a/locale/ExpCore/server.lua b/locale/ExpCore/server.lua index 8b232c29..77a6ea1a 100644 --- a/locale/ExpCore/server.lua +++ b/locale/ExpCore/server.lua @@ -10,7 +10,6 @@ Discord: https://discord.gg/r6dC2uK -- server allows control over threads and other features the devs missed out local Server = {} Server._thread = {} -Server._thread.__index = Server._thread --- Returns a un-used uuid (better system needed) -- @usage obj.uuid = Server.new_uuid() @@ -80,7 +79,7 @@ end function Server.close_all_threads(with_force) if not with_force then for uuid,next_thread in pairs(Server.threads()) do - next_thread:close() + if uuid ~= '_n' then next_thread:close() end end else Server._threads(true) @@ -186,6 +185,7 @@ if commands._expgaming then local callback = args.code if not string.find(callback,'%s') and not string.find(callback,'return') then callback = 'return '..callback end if game.player then callback = 'local player, surface, force = game.player, game.player.surface, game.player.force '..callback end + if Ranking and Ranking.get_rank then callback = 'local rank = Ranking.get_rank(game.player) '..callback end local success, err = Server.interface(callback) player_return(err) end) @@ -198,7 +198,7 @@ end -- @treturn table the new thread object function Server._thread:create(obj) local obj = obj or {} - setmetatable(obj,Server._thread) + setmetatable(obj,{__index=Server._thread}) obj.uuid = Server.new_uuid() return obj end @@ -366,7 +366,7 @@ end) Event.register(-2,function(event) local threads = Server.threads() for uuid,thread in pairs(threads) do - setmetatable(thread,Server._thread) + if uuid ~= '_n' then setmetatable(thread,{__index=Server._thread}) end end end) diff --git a/locale/StdLib/table.lua b/locale/StdLib/table.lua index 557b2beb..6f5c8166 100644 --- a/locale/StdLib/table.lua +++ b/locale/StdLib/table.lua @@ -490,8 +490,8 @@ end -- table.autokey(tbl,'f') -- return 1 function table.autokey(tbl,str) local _return = {} - for key,value in pairs(keys) do - if string.contains(string.lower(string),string.lower(key)) then table.insert(_return,value) end + for key,value in pairs(tbl) do + if string.contains(string.lower(str),string.lower(key)) then table.insert(_return,value) end end return _return[1] or false end \ No newline at end of file diff --git a/locale/en/exp-core.cfg b/locale/en/exp-core.cfg index af1162f1..a9acca3b 100644 --- a/locale/en/exp-core.cfg +++ b/locale/en/exp-core.cfg @@ -4,4 +4,11 @@ help-format= __1__ __2__ unauthorized=401 - Unauthorized: Access is denied due to invalid credentials invalid-inputs=Invalid Input, /__1__ __2__ invalid-player=Invaild Player Name, __1__ ,try using tab key to auto-complete the name -command-ran=Command Complete \ No newline at end of file +command-ran=Command Complete + +[ranking] +all-rank-print=[Everyone]: __1__ +rank-up=__1__ was promoted to __2__ by __3__ +rank-down=__1__ was demoted to __2__ by __3__ +rank-given=You have been given the __1__ Rank! +tag-reset=Your Tag was reset due to a Rank change \ No newline at end of file