mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 11:35:22 +09:00
Added Module: ExpGamingCore
This commit is contained in:
151
modules/ExpGamingCore/Commands/control.lua
Normal file
151
modules/ExpGamingCore/Commands/control.lua
Normal file
@@ -0,0 +1,151 @@
|
||||
--[[
|
||||
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-----------------------------------------------------------
|
||||
local command_calls = {}
|
||||
local command_data = {}
|
||||
|
||||
--- Uses a commands data to return the inputs as a string
|
||||
-- @usage command = command_data[command_name]
|
||||
-- command_inputs(command) -- returns "<input1> <input2> "
|
||||
-- @tparam table the data for the command being run
|
||||
-- @treturn string the inputs in string format
|
||||
local function command_inputs(command)
|
||||
if not is_type(command,'table') then return end
|
||||
local inputs = ''
|
||||
for _,input in pairs(command.inputs) do
|
||||
if input == true then break end
|
||||
inputs = inputs..'<'..input..'> '
|
||||
end
|
||||
return inputs
|
||||
end
|
||||
|
||||
--- Uses the command data and the event to return a table of the args
|
||||
-- @usage command = command_data[command_name]
|
||||
-- command_args(event,command) -- return {input1='one',input2='two'}
|
||||
-- @tparam defines.events.on_console_command event the event rasied by the command
|
||||
-- @tparam table command the data for the command being run
|
||||
-- @treturn table a table version of the event.parameter based on expected inputs
|
||||
local function command_args(event,command)
|
||||
if not event or not is_type(command,'table') then return end
|
||||
local args = {}
|
||||
-- haddles no parameters given
|
||||
if not event.parameter then
|
||||
if #command.inputs > 0 then return args, false
|
||||
else return args, true
|
||||
end
|
||||
end
|
||||
-- finds all the words and cheaks if the right number were given
|
||||
local words = string.split(event.parameter,' ')
|
||||
if table.last(command.inputs) == true then
|
||||
if #words < #command.inputs-1 then return args, false end
|
||||
else
|
||||
if #words < #command.inputs then return args, false end
|
||||
end
|
||||
-- if it is the right number then process and return the args
|
||||
for index,input in pairs(command.inputs) do
|
||||
if command.inputs[index+1] == true then
|
||||
args[input] = table.concat(words,' ',index)
|
||||
break
|
||||
else
|
||||
args[input] = words[index]
|
||||
end
|
||||
end
|
||||
return args, true
|
||||
end
|
||||
|
||||
--- Used to return all the commands a player can use
|
||||
-- @usage get_commands(1) -- return {{command data},{command data}}
|
||||
-- @param player the player refreced by string|number|LuaPlayer|event
|
||||
-- @treturn table a table containg all the commands the player can use
|
||||
function commands.get_commands(player)
|
||||
local commands = {}
|
||||
local player = Game.get_player(player)
|
||||
if not player then return commands end
|
||||
local rank = Ranking.get_rank(player)
|
||||
for name,data in pairs(command_data) do
|
||||
if rank:allowed(name) then table.insert(commands,data) end
|
||||
end
|
||||
return commands
|
||||
end
|
||||
|
||||
--- Used to call the custom commands
|
||||
-- @usage You dont its an internal command
|
||||
-- @tparam defines.events.on_console_command command 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(command) and Game.get_player(command).name or 'server'
|
||||
-- is the player allowed to use this command
|
||||
if is_type(Ranking,'table') and Ranking._presets and Ranking._presets().meta.rank_count > 0 and not Ranking.get_rank(player_name):allowed(command.name) then
|
||||
player_return({'commands.unauthorized'},defines.textcolor.crit)
|
||||
if game.player then game.player.play_sound{path='utility/cannot_build'} end
|
||||
game.write_file('commands.log',
|
||||
game.tick
|
||||
..' Player: "'..player_name..'"'
|
||||
..' Failed to use command (Unauthorized): "'..command.name..'"'
|
||||
..' With args of: '..table.tostring(command_args(command,command_data))
|
||||
..'\n'
|
||||
, true, 0)
|
||||
return
|
||||
end
|
||||
-- gets the args for the command
|
||||
local args, valid = command_args(command,command_data)
|
||||
if not valid then
|
||||
player_return({'commands.invalid-inputs',command.name,command_inputs(command_data)},defines.textcolor.high)
|
||||
if game.player then game.player.play_sound{path='utility/deconstruct_big'} end
|
||||
game.write_file('commands.log',
|
||||
game.tick
|
||||
..' Player: "'..player_name..'"'
|
||||
..' Failed to use command (Invalid Args): "'..command.name..'"'
|
||||
..' With args of: '..table.tostring(args)
|
||||
..'\n'
|
||||
, true, 0)
|
||||
return
|
||||
end
|
||||
-- runs the command
|
||||
local success, err = pcall(command_calls[command.name],command,args)
|
||||
if not success then error(err) end
|
||||
if err ~= commands.error and player_name ~= 'server' then player_return({'commands.command-ran'},defines.textcolor.info) end
|
||||
game.write_file('commands.log',
|
||||
game.tick
|
||||
..' Player: "'..player_name..'"'
|
||||
..' Used command: "'..command.name..'"'
|
||||
..' With args of: '..table.tostring(args)
|
||||
..'\n'
|
||||
, true, 0)
|
||||
end
|
||||
|
||||
-- this is a set of constants you can use
|
||||
commands._add_command = commands.add_command --if you dont want to use the custom commands interface
|
||||
commands.expgaming = true --if you want to test if the custom commands are present
|
||||
commands.error = {} --if returned during a custom command, Command Complete message not printed
|
||||
--- Used to define commands
|
||||
-- @usage inputs = {'player','reason',true}
|
||||
-- commands.add_command('ban','bans a player',inputs,function() return end)
|
||||
-- @tparam string name the name of the command
|
||||
-- @tparam[opt='No Description'] string description the description of the command
|
||||
-- @tparam[opt={'parameter',true}] table inputs a table of the inputs to be used, last index being true makes the last parameter open ended (longer than one word)
|
||||
-- @tparam function event the function to call on the event
|
||||
commands.add_command = function(name, description, inputs, event)
|
||||
if command_calls[name] then return end
|
||||
if not is_type(name,'string') then return end
|
||||
if not is_type(event,'function') then return end
|
||||
verbose('Created Command: '..name)
|
||||
local description = is_type(description,'string') and description or 'No Description'
|
||||
local inputs = is_type(inputs,'table') and inputs or {'parameter',true}
|
||||
command_data[name] = {
|
||||
name=name,
|
||||
description=description,
|
||||
inputs=inputs
|
||||
}
|
||||
command_calls[name] = event
|
||||
commands._add_command(name,command_inputs(command_data[name])..'- '..description,function(...)
|
||||
local success, err = pcall(run_custom_command,...)
|
||||
if not success then error(err) end
|
||||
end)
|
||||
end
|
||||
209
modules/ExpGamingCore/Gui/GuiParts/center.lua
Normal file
209
modules/ExpGamingCore/Gui/GuiParts/center.lua
Normal file
@@ -0,0 +1,209 @@
|
||||
--[[
|
||||
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
|
||||
]]
|
||||
|
||||
local center = {}
|
||||
center._center = {}
|
||||
|
||||
--- Adds a new obj to the center gui
|
||||
-- @usage Gui.center.add{name='foo',caption='Foo',tooltip='Testing',draw=function}
|
||||
-- @param obj contains the new object, needs name, fraw is opt and is function(root_frame)
|
||||
-- @return the object made, used to add tabs
|
||||
function center.add(obj)
|
||||
if not is_type(obj,'table') then return end
|
||||
if not is_type(obj.name,'string') then return end
|
||||
verbose('Created Center Gui: '..obj.name)
|
||||
setmetatable(obj,{__index=center._center})
|
||||
obj.tabs = {}
|
||||
obj._tabs = {}
|
||||
Gui._add_data('center',obj.name,obj)
|
||||
Gui.toolbar.add(obj.name,obj.caption,obj.tooltip,obj.open)
|
||||
return obj
|
||||
end
|
||||
|
||||
--- Used to get the center frame of the player, used mainly in script
|
||||
-- @usage Gui.center.get_flow(player) -- returns gui emelemt
|
||||
-- @param player a player indifier to get the flow for
|
||||
-- @treturn table the gui element flow
|
||||
function center.get_flow(player)
|
||||
local player = Game.get_player(player)
|
||||
return player.gui.center.exp_center or player.gui.center.add{name='exp_center',type='flow'}
|
||||
end
|
||||
|
||||
--- Used to open a center frame for a player
|
||||
-- @usage Gui.center.open(player,'server-info') -- return true
|
||||
-- @param player a player indifier to get the flow for
|
||||
-- @tparam string center the name of the center frame to open
|
||||
-- @treturn boelon based on if it successed or not
|
||||
function center.open(player,center)
|
||||
local player = Game.get_player(player)
|
||||
Gui.center.clear(player)
|
||||
if not Gui._get_data('center')[center] then return false end
|
||||
Gui._get_data('center')[center].open{
|
||||
element={name=center},
|
||||
player_index=player.index
|
||||
}
|
||||
return true
|
||||
end
|
||||
|
||||
--- Used to open a center frame for a player
|
||||
-- @usage Gui.center.open_tab(player,'readme','rules') -- return true
|
||||
-- @param player a player indifier to get the flow for
|
||||
-- @tparam string center the name of the center frame to open
|
||||
-- @tparam string tab the name of the tab to open
|
||||
-- @treturn boelon based on if it successed or not
|
||||
function center.open_tab(player,center,tab)
|
||||
local player = Game.get_player(player)
|
||||
if not Gui.center.open(player,center) then return false end
|
||||
local name = center..'_'..tab
|
||||
if not Gui._get_data('inputs_button')[name] then return false end
|
||||
Gui._get_data('inputs_button')[name].events[defines.events.on_gui_click]{
|
||||
element=Gui.center.get_flow(player)[center].tab_bar.tab_bar_scroll.tab_bar_scroll_flow[name],
|
||||
}
|
||||
return true
|
||||
end
|
||||
|
||||
--- Used to clear the center frame of the player, used mainly in script
|
||||
-- @usage Gui.center.clear(player)
|
||||
-- @param player a player indifier to get the flow for
|
||||
function center.clear(player)
|
||||
local player = Game.get_player(player)
|
||||
center.get_flow(player).clear()
|
||||
end
|
||||
|
||||
-- used on the button press when the toolbar button is press, can be overriden
|
||||
-- not recomented for direct use see Gui.center.open
|
||||
function center._center.open(event)
|
||||
local player = Game.get_player(event)
|
||||
local _center = Gui._get_data('center')[event.element.name]
|
||||
local center_flow = center.get_flow(player)
|
||||
if center_flow[_center.name] then Gui.center.clear(player) return end
|
||||
local center_frame = center_flow.add{
|
||||
name=_center.name,
|
||||
type='frame',
|
||||
caption=_center.caption,
|
||||
direction='vertical',
|
||||
style=mod_gui.frame_style
|
||||
}
|
||||
if is_type(center_frame.caption,'string') and player.gui.is_valid_sprite_path(center_frame.caption) then center_frame.caption = '' end
|
||||
if is_type(_center.draw,'function') then
|
||||
local success, err = pcall(_center.draw,_center,center_frame)
|
||||
if not success then error(err) end
|
||||
else error('No Callback on center frame '.._center.name)
|
||||
end
|
||||
player.opened=center_frame
|
||||
end
|
||||
|
||||
-- this is the default draw function if one is not provided, can be overriden
|
||||
-- not recomented for direct use see Gui.center.open
|
||||
function center._center:draw(frame)
|
||||
Gui.bar(frame,510)
|
||||
local tab_bar = frame.add{
|
||||
type='frame',
|
||||
name='tab_bar',
|
||||
style='image_frame',
|
||||
direction='vertical'
|
||||
}
|
||||
tab_bar.style.width = 510
|
||||
tab_bar.style.height = 65
|
||||
local tab_bar_scroll = tab_bar.add{
|
||||
type='scroll-pane',
|
||||
name='tab_bar_scroll',
|
||||
horizontal_scroll_policy='auto-and-reserve-space',
|
||||
vertical_scroll_policy='never'
|
||||
}
|
||||
tab_bar_scroll.style.vertically_squashable = false
|
||||
tab_bar_scroll.style.vertically_stretchable = true
|
||||
tab_bar_scroll.style.width = 500
|
||||
local tab_bar_scroll_flow = tab_bar_scroll.add{
|
||||
type='flow',
|
||||
name='tab_bar_scroll_flow',
|
||||
direction='horizontal'
|
||||
}
|
||||
Gui.bar(frame,510)
|
||||
local tab = frame.add{
|
||||
type ='frame',
|
||||
name='tab',
|
||||
direction='vertical',
|
||||
style='image_frame'
|
||||
}
|
||||
tab.style.width = 510
|
||||
tab.style.height = 305
|
||||
local tab_scroll = tab.add{
|
||||
type ='scroll-pane',
|
||||
name='tab_scroll',
|
||||
horizontal_scroll_policy='never',
|
||||
vertical_scroll_policy='auto'
|
||||
}
|
||||
tab_scroll.style.vertically_squashable = false
|
||||
tab_scroll.style.vertically_stretchable = true
|
||||
tab_scroll.style.width = 500
|
||||
local tab_scroll_flow = tab_scroll.add{
|
||||
type='flow',
|
||||
name='tab_scroll_flow',
|
||||
direction='vertical'
|
||||
}
|
||||
tab_scroll_flow.style.width = 480
|
||||
Gui.bar(frame,510)
|
||||
local first_tab = nil
|
||||
for name,button in pairs(self.tabs) do
|
||||
first_tab = first_tab or name
|
||||
button:draw(tab_bar_scroll_flow).style.font_color = defines.color.white
|
||||
end
|
||||
self._tabs[self.name..'_'..first_tab](tab_scroll_flow)
|
||||
tab_bar_scroll_flow.children[1].style.font_color = defines.color.orange
|
||||
frame.parent.add{type='frame',name='temp'}.destroy()--recenter the GUI
|
||||
end
|
||||
|
||||
--- If deafult draw is used then you can add tabs to the gui with this function
|
||||
-- @usage _center:add_tab('foo','Foo','Just a tab',function)
|
||||
-- @tparam string name this is the name of the tab
|
||||
-- @tparam string caption this is the words that appear on the tab button
|
||||
-- @tparam[opt] string tooltip the tooltip that is on the button
|
||||
-- @tparam function callback this is called when button is pressed with function(root_frame)
|
||||
-- @return self to allow chaining of _center:add_tab
|
||||
function center._center:add_tab(name,caption,tooltip,callback)
|
||||
verbose('Created Tab: '..self.name..'/'..name)
|
||||
self._tabs[self.name..'_'..name] = callback
|
||||
self.tabs[name] = Gui.inputs.add{
|
||||
type='button',
|
||||
name=self.name..'_'..name,
|
||||
caption=caption,
|
||||
tooltip=tooltip
|
||||
}:on_event('click',function(event)
|
||||
local tab = event.element.parent.parent.parent.parent.tab.tab_scroll.tab_scroll_flow
|
||||
tab.clear()
|
||||
local frame_name = tab.parent.parent.parent.name
|
||||
local _center = Gui._get_data('center')[frame_name]
|
||||
local _tab = _center._tabs[event.element.name]
|
||||
if is_type(_tab,'function') then
|
||||
for _,button in pairs(event.element.parent.children) do
|
||||
if button.name == event.element.name then
|
||||
button.style.font_color = defines.color.orange
|
||||
else
|
||||
button.style.font_color = defines.color.white
|
||||
end
|
||||
end
|
||||
local success, err = pcall(_tab,tab)
|
||||
if not success then error(err) end
|
||||
end
|
||||
end)
|
||||
return self
|
||||
end
|
||||
|
||||
-- used so that when gui close key is pressed this will close the gui
|
||||
Event.register(defines.events.on_gui_closed,function(event)
|
||||
if event.element and event.element.valid then event.element.destroy() end
|
||||
end)
|
||||
|
||||
-- when the player rank is changed it closses the center guis
|
||||
if defines.events.rank_change then
|
||||
Event.register(defines.events.rank_change,center.clear)
|
||||
end
|
||||
|
||||
return center
|
||||
375
modules/ExpGamingCore/Gui/GuiParts/inputs.lua
Normal file
375
modules/ExpGamingCore/Gui/GuiParts/inputs.lua
Normal file
@@ -0,0 +1,375 @@
|
||||
--[[
|
||||
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
|
||||
]]
|
||||
|
||||
local inputs = {}
|
||||
inputs._input = {}
|
||||
-- these are just so you can have short cuts to this
|
||||
inputs.events = {
|
||||
error='error',
|
||||
state=defines.events.on_gui_checked_state_changed,
|
||||
click=defines.events.on_gui_click,
|
||||
elem=defines.events.on_gui_elem_changed,
|
||||
selection=defines.events.on_gui_selection_state_changed,
|
||||
text=defines.events.on_gui_text_changed,
|
||||
slider=defines.events.on_gui_value_changed
|
||||
}
|
||||
|
||||
--- Sets the input to trigger on an certain event
|
||||
-- @usage button:on_event(defines.events.on_gui_click,player_return)
|
||||
-- @param event the event to raise callback on | can be number of the event | can be a key of inputs.events
|
||||
-- @tparam function callback the function you want to run on the event
|
||||
-- @treturn table returns self so you can chain together
|
||||
function inputs._input:on_event(event,callback)
|
||||
if not is_type(callback,'function') then return self end
|
||||
if inputs.events[event] then event = inputs.events[event] end
|
||||
if event == 'error' then self._error = callback return self end
|
||||
self.events[event] = callback
|
||||
return self
|
||||
end
|
||||
|
||||
--- Draw the input into the root element
|
||||
-- @usage button:draw(frame)
|
||||
-- @param root the element you want to add the input to
|
||||
-- @return returns the element that was added
|
||||
function inputs._input:draw(root)
|
||||
local player = Game.get_player(root.player_index)
|
||||
if is_type(self.draw_data.caption,'string') and player.gui.is_valid_sprite_path(self.draw_data.caption) then
|
||||
local data = table.deepcopy(self.draw_data)
|
||||
data.type = 'sprite-button'
|
||||
data.sprite = data.caption
|
||||
data.caption = nil
|
||||
return root.add(data)
|
||||
elseif is_type(self.draw_data.sprite,'string') and player.gui.is_valid_sprite_path(self.draw_data.sprite) then
|
||||
local data = table.deepcopy(self.draw_data)
|
||||
data.type = 'sprite-button'
|
||||
return root.add(data)
|
||||
elseif is_type(self.data._state,'function') then
|
||||
local data = table.deepcopy(self.draw_data)
|
||||
local success, err = pcall(self.data._state,player,root)
|
||||
if success then data.state = err else error(err) end
|
||||
return root.add(data)
|
||||
elseif is_type(self.data._start,'function') then
|
||||
local data = table.deepcopy(self.draw_data)
|
||||
local success, err = pcall(self.data._start,player,root)
|
||||
if success then data.value = err else error(err) end
|
||||
return root.add(data)
|
||||
elseif is_type(self.data._index,'function') then
|
||||
local data = table.deepcopy(self.draw_data)
|
||||
local success, err = pcall(self.data._index,player,root)
|
||||
if success then data.selected_index = err else error(err) end
|
||||
if is_type(self.data._items,'function') then
|
||||
local success, err = pcall(self.data._items,player,root)
|
||||
if success then data.items = err else error(err) end
|
||||
end
|
||||
return root.add(data)
|
||||
elseif is_type(self.data._items,'function') then
|
||||
local data = table.deepcopy(self.draw_data)
|
||||
local success, err = pcall(self.data._items,player,root)
|
||||
if success then data.items = err else error(err) end
|
||||
if is_type(self.data._index,'function') then
|
||||
local success, err = pcall(self.data._index,player,root)
|
||||
if success then data.selected_index = err else error(err) end
|
||||
end
|
||||
return root.add(data)
|
||||
else
|
||||
return root.add(self.draw_data)
|
||||
end
|
||||
end
|
||||
|
||||
--- Add a new input, this is the same as doing frame.add{} but returns a diffrent object
|
||||
-- @usage Gui.inputs.add{type='button',name='test',caption='Test'}
|
||||
-- @tparam table obj the new element to add if caption is a sprite path then sprite is used
|
||||
-- @treturn table the custom input object
|
||||
function inputs.add(obj)
|
||||
if not is_type(obj,'table') then return end
|
||||
if not is_type(obj.type,'string') then return end
|
||||
local type = obj.type
|
||||
if type == 'button' or
|
||||
type == 'sprite-button' or
|
||||
type == 'choose-elem-button' or
|
||||
type == 'checkbox' or
|
||||
type == 'radiobutton' or
|
||||
type == 'textfield' or
|
||||
type == 'text-box' or
|
||||
type == 'slider' or
|
||||
type == 'drop-down'
|
||||
then else return end
|
||||
verbose('Created Input: '..obj.name..' ('..obj.type..')')
|
||||
if obj.type == 'button' or obj.type == 'sprite-button' then obj.style = mod_gui.button_style end
|
||||
obj.draw_data = table.deepcopy(obj)
|
||||
obj.data = {}
|
||||
obj.events = {}
|
||||
setmetatable(obj,{__index=inputs._input})
|
||||
Gui._add_data('inputs_'..type,obj.name,obj)
|
||||
return obj
|
||||
end
|
||||
|
||||
-- this just runs the events given to inputs
|
||||
function inputs._event_handler(event)
|
||||
if not event.element then return end
|
||||
local elements = Gui._get_data('inputs_'..event.element.type) or {}
|
||||
local element = elements[event.element.name]
|
||||
if not element and event.element.type == 'sprite-button' then
|
||||
elements = Gui._get_data('inputs_button') or {}
|
||||
element = elements[event.element.name]
|
||||
end
|
||||
if element then
|
||||
if not is_type(element.events[event.name],'function') then return end
|
||||
local success, err = pcall(element.events[event.name],event)
|
||||
if not success then
|
||||
if is_type(element._error,'function') then pcall(element._error)
|
||||
else error(err) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Event.register(inputs.events.state,inputs._event_handler)
|
||||
Event.register(inputs.events.click,inputs._event_handler)
|
||||
Event.register(inputs.events.elem,inputs._event_handler)
|
||||
Event.register(inputs.events.state,inputs._event_handler)
|
||||
Event.register(inputs.events.text,inputs._event_handler)
|
||||
Event.register(inputs.events.slider,inputs._event_handler)
|
||||
Event.register(inputs.events.selection,inputs._event_handler)
|
||||
|
||||
-- the folwing functions are just to make inputs easier but if what you want is not include use inputs.add(obj)
|
||||
--- Used to define a button, can have many function
|
||||
-- @usage Gui.inputs.add_button('test','Test','Just for testing',{{condition,callback},...})
|
||||
-- @tparam string name the name of this button
|
||||
-- @tparam string the display for this button, either text or sprite path
|
||||
-- @tparam string tooltip the tooltip to show on the button
|
||||
-- @param callbacks can either be a single function or a list of function pairs see exaplmes at bottom
|
||||
-- @treturn table the button object that was made, to allow a custom error event if wanted
|
||||
function inputs.add_button(name,display,tooltip,callbacks)
|
||||
local button = inputs.add{
|
||||
type='button',
|
||||
name=name,
|
||||
caption=display,
|
||||
tooltip=tooltip
|
||||
}
|
||||
button.data._callbacks = callbacks
|
||||
button:on_event('click',function(event)
|
||||
local elements = Gui._get_data('inputs_'..event.element.type) or {}
|
||||
local button = elements[event.element.name]
|
||||
if not button and event.element.type == 'sprite-button' then
|
||||
elements = Gui._get_data('inputs_button') or {}
|
||||
button = elements[event.element.name]
|
||||
end
|
||||
local player = Game.get_player(event)
|
||||
local mouse = event.button
|
||||
local keys = {alt=event.alt,ctrl=event.control,shift=event.shift}
|
||||
local element = event.element
|
||||
local callbacks = button.data._callbacks
|
||||
if is_type(callbacks,'function') then callbacks = {{function(...) return true end,callbacks}} end
|
||||
for _,data in pairs(callbacks) do
|
||||
if is_type(data[1],'function') and is_type(data[2],'function') then
|
||||
local success, err = pcall(data[1],player,mouse,keys,event)
|
||||
if success and err == true then
|
||||
local success, err = pcall(data[2],player,element,event)
|
||||
if not success then error(err) end
|
||||
elseif not success then error(err) end
|
||||
else error('Invalid Callback Condition Format') end
|
||||
end
|
||||
end)
|
||||
return button
|
||||
end
|
||||
|
||||
--- Used to define a choose-elem-button callback only on elem_changed
|
||||
-- @usage Gui.inputs.add_elem_button('test','Test','Just for testing',function)
|
||||
-- @tparam string name the name of this button
|
||||
-- @tparam string elem_type the display for this button, either text or sprite path
|
||||
-- @tparam string tooltip the tooltip to show on the button
|
||||
-- @tparam function callback the callback to call on change function(player,element,elem)
|
||||
-- @treturn table the button object that was made, to allow a custom error event if wanted
|
||||
function inputs.add_elem_button(name,elem_type,tooltip,callback)
|
||||
local button = inputs.add{
|
||||
type='choose-elem-button',
|
||||
name=name,
|
||||
elem_type=elem_type,
|
||||
tooltip=tooltip
|
||||
}
|
||||
button.data._callback = callback
|
||||
button:on_event('elem',function(event)
|
||||
local button = Gui._get_data('inputs_'..event.element.type)[event.element.name]
|
||||
local player = Game.get_player(event)
|
||||
local element = event.element or {elem_type=nil,elem_value=nil}
|
||||
local elem = {type=element.elem_type,value=element.elem_value}
|
||||
if is_type(button.data._callback,'function') then
|
||||
local success, err = pcall(button.data._callback,player,element,elem)
|
||||
if not success then error(err) end
|
||||
else error('Invalid Callback') end
|
||||
end)
|
||||
return button
|
||||
end
|
||||
|
||||
--- Used to define a checkbox callback only on state_changed
|
||||
-- @usage Gui.inputs.add_checkbox('test',false,'Just for testing',function,function,funvtion)
|
||||
-- @tparam string name the name of this button
|
||||
-- @tparam boolean radio if this is a radio button
|
||||
-- @tparam string display the display for this button, either text or sprite path
|
||||
-- @tparam function default the callback which choses the default check state
|
||||
-- @tparam function callback_true the callback to call when changed to true
|
||||
-- @tparam function callback_false the callback to call when changed to false
|
||||
-- @treturn table the button object that was made, to allow a custom error event if wanted
|
||||
function inputs.add_checkbox(name,radio,display,default,callback_true,callback_false)
|
||||
local type = 'checkbox'; if radio then type='radiobutton' end
|
||||
local state = false; if is_type(default,'boolean') then state = default end
|
||||
local checkbox = inputs.add{
|
||||
type=type,
|
||||
name=name,
|
||||
caption=display,
|
||||
state=state
|
||||
}
|
||||
if is_type(default,'function') then checkbox.data._state = default end
|
||||
checkbox.data._true = callback_true
|
||||
checkbox.data._false = callback_false
|
||||
checkbox:on_event('state',function(event)
|
||||
local checkbox = Gui._get_data('inputs_'..event.element.type)[event.element.name]
|
||||
local player = Game.get_player(event)
|
||||
local state = event.element.state
|
||||
if state then
|
||||
if is_type(checkbox.data._true,'function') then
|
||||
local success, err = pcall(checkbox.data._true,player,event.element)
|
||||
if not success then error(err) end
|
||||
else error('Invalid Callback') end
|
||||
else
|
||||
if is_type(checkbox.data._false,'function') then
|
||||
local success, err = pcall(checkbox.data._false,player,event.element)
|
||||
if not success then error(err) end
|
||||
else error('Invalid Callback') end
|
||||
end
|
||||
end)
|
||||
return checkbox
|
||||
end
|
||||
|
||||
--- Used to reset the state of radio buttons, recomened to be called on_state_change to reset any radio buttons it is ment to work with.
|
||||
-- @usage Gui.inputs.reset_radio{radio1,radio2,...}
|
||||
-- @param elements can be a list of elements or a single element
|
||||
function inputs.reset_radio(elements)
|
||||
if #elements > 0 then
|
||||
for _,element in pairs(elements) do
|
||||
if element.valid then
|
||||
local _elements = Gui._get_data('inputs_'..element.type) or {}
|
||||
local _element = _elements[element.name]
|
||||
local player = Game.get_player(element.player_index)
|
||||
local state = false
|
||||
local success, err = pcall(_element.data._state,player,element.parent)
|
||||
if success then state = err else error(err) end
|
||||
element.state = state
|
||||
end
|
||||
end
|
||||
else
|
||||
if elements.valid then
|
||||
local _elements = Gui._get_data('inputs_'..elements.type) or {}
|
||||
local _element = _elements[elements.name]
|
||||
local player = Game.get_player(elements.player_index)
|
||||
local state = false
|
||||
local success, err = pcall(_element.data._state,player,elements.parent)
|
||||
if success then state = err else error(err) end
|
||||
elements.state = state
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Used to define a text callback only on text_changed
|
||||
-- @usage Gui.inputs.add_text('test',false,'Just for testing',function)
|
||||
-- @tparam string name the name of this button
|
||||
-- @tparam boolean box is it a text box rather than a text field
|
||||
-- @tparam string text the starting text
|
||||
-- @tparam function callback the callback to call on change function(player,text,element)
|
||||
-- @treturn table the text object that was made, to allow a custom error event if wanted
|
||||
function inputs.add_text(name,box,text,callback)
|
||||
local type = 'textfield'; if box then type='text-box' end
|
||||
local textbox = inputs.add{
|
||||
type=type,
|
||||
name=name,
|
||||
text=text
|
||||
}
|
||||
textbox.data._callback = callback
|
||||
textbox:on_event('text',function(event)
|
||||
local textbox = Gui._get_data('inputs_'..event.element.type)[event.element.name]
|
||||
local player = Game.get_player(event)
|
||||
local element = event.element
|
||||
local callback = textbox.data._callback
|
||||
if is_type(callback,'function') then
|
||||
local success, err = pcall(callback,player,element.text,element)
|
||||
if not success then error(err) end
|
||||
else error('Invalid Callback Condition Format') end
|
||||
end)
|
||||
return textbox
|
||||
end
|
||||
|
||||
--- Used to define a slider callback only on value_changed
|
||||
-- @usage Gui.inputs.add_slider('test','horizontal',1,10,5,function)
|
||||
-- @tparam string name the name of this button
|
||||
-- @tparam string orientation direction of the slider
|
||||
-- @tparam number min the lowest number
|
||||
-- @tparam number max the highest number
|
||||
-- @tparam function start_callback either a number or a function to return a number
|
||||
-- @tparam function callback the function to be called on value_changed function(player,value,percent,element)
|
||||
-- @treturn table the slider object that was made, to allow a custom error event if wanted
|
||||
function inputs.add_slider(name,orientation,min,max,start_callback,callback)
|
||||
local slider = inputs.add{
|
||||
type='slider',
|
||||
name=name,
|
||||
orientation=orientation,
|
||||
minimum_value=min,
|
||||
maximum_value=max,
|
||||
value=start_callback
|
||||
}
|
||||
slider.data._start = start_callback
|
||||
slider.data._callback = callback
|
||||
slider:on_event('slider',function(event)
|
||||
local slider = Gui._get_data('inputs_'..event.element.type)[event.element.name]
|
||||
local player = Game.get_player(event)
|
||||
local value = event.element.slider_value
|
||||
local data = slider.data
|
||||
local percent = value/event.element.get_slider_maximum()
|
||||
if is_type(data._callback,'function') then
|
||||
local success, err = pcall(data._callback,player,value,percent,event.element)
|
||||
if not success then error(err) end
|
||||
else error('Invalid Callback Condition Format') end
|
||||
end)
|
||||
return slider
|
||||
end
|
||||
|
||||
--- Used to define a drop down callback only on value_changed
|
||||
-- @usage Gui.inputs.add_drop_down('test',{1,2,3},1,function)
|
||||
-- @tparam string name name of the drop down
|
||||
-- @param items either a list or a function which returns a list
|
||||
-- @param index either a number or a function which returns a number
|
||||
-- @tparam function callback the callback which is called when a new index is selected function(player,selected,items,element)
|
||||
-- @treturn table the drop-down object that was made, to allow a custom error event if wanted
|
||||
function inputs.add_drop_down(name,items,index,callback)
|
||||
local drop_down = inputs.add{
|
||||
type='drop-down',
|
||||
name=name,
|
||||
items=items,
|
||||
selected_index=index
|
||||
}
|
||||
drop_down.data._items = items
|
||||
drop_down.data._index = index
|
||||
drop_down.data._callback = callback
|
||||
drop_down:on_event('selection',function(event)
|
||||
local drop_down = Gui._get_data('inputs_'..event.element.type)[event.element.name]
|
||||
local player = Game.get_player(event)
|
||||
local element = event.element
|
||||
local items = element.items
|
||||
local selected = items[element.selected_index]
|
||||
local callback = drop_down.data._callback
|
||||
if is_type(callback,'function') then
|
||||
local success, err = pcall(callback,player,selected,items,element)
|
||||
if not success then error(err) end
|
||||
else error('Invalid Callback Condition Format') end
|
||||
end)
|
||||
return drop_down
|
||||
end
|
||||
|
||||
return inputs
|
||||
|
||||
-- to see examples look at GuiParts/test.lua
|
||||
177
modules/ExpGamingCore/Gui/GuiParts/left.lua
Normal file
177
modules/ExpGamingCore/Gui/GuiParts/left.lua
Normal file
@@ -0,0 +1,177 @@
|
||||
--[[
|
||||
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
|
||||
]]
|
||||
|
||||
local left = {}
|
||||
left._left = {}
|
||||
|
||||
-- used for debugging
|
||||
function left.override_open(state)
|
||||
Gui._global().over_ride_left_can_open = state
|
||||
end
|
||||
--- Used to add a left gui frame
|
||||
-- @usage Gui.left.add{name='foo',caption='Foo',tooltip='just testing',open_on_join=true,can_open=function,draw=function}
|
||||
-- @param obj this is what will be made, needs a name and a draw function(root_frame), open_on_join can be used to set the deaful state true/false, can_open is a test to block it from opening but is not needed
|
||||
-- @return the object that is made to... well idk but for the future
|
||||
function left.add(obj)
|
||||
if not is_type(obj,'table') then return end
|
||||
if not is_type(obj.name,'string') then return end
|
||||
verbose('Created Left Gui: '..obj.name)
|
||||
setmetatable(obj,{__index=left._left})
|
||||
Gui._add_data('left',obj.name,obj)
|
||||
Gui.toolbar.add(obj.name,obj.caption,obj.tooltip,obj.toggle)
|
||||
return obj
|
||||
end
|
||||
|
||||
--- This is used to update all the guis of conected players, good idea to use our thread system as it as nested for loops
|
||||
-- @usage Gui.left.update()
|
||||
-- @tparam[opt] string frame this is the name of a frame if you only want to update one
|
||||
-- @param[opt] players the player to update for, if not given all players are updated, can be one player
|
||||
function left.update(frame,players)
|
||||
if not Server or not Server._thread then
|
||||
local players = is_type(players,'table') and #players > 0 and {unpack(players)} or is_type(players,'table') and {players} or Game.get_player(players) and {Game.get_player(players)} or game.connected_players
|
||||
for _,player in pairs(players) do
|
||||
local frames = Gui._get_data('left') or {}
|
||||
if frame then frames = {[frame]=frames[frame]} or {} end
|
||||
for name,left in pairs(frames) do
|
||||
if _left then
|
||||
local fake_event = {player_index=player.index,element={name=name}}
|
||||
left.open(fake_event)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local frames = Gui._get_data('left') or {}
|
||||
if frame then frames = {[frame]=frames[frame]} or {} end
|
||||
local players = is_type(players,'table') and #players > 0 and {unpack(players)} or is_type(players,'table') and {players} or Game.get_player(players) and {Game.get_player(players)} or game.connected_players
|
||||
Server.new_thread{
|
||||
data={players=players,frames=frames}
|
||||
}:on_event('tick',function(thread)
|
||||
if #thread.data.players == 0 then thread:close() return end
|
||||
local player = table.remove(thread.data.players,1)
|
||||
Server.new_thread{
|
||||
data={player=player,frames=thread.data.frames}
|
||||
}:on_event('resolve',function(thread)
|
||||
for name,left in pairs(thread.data.frames) do
|
||||
if left then
|
||||
local fake_event = {player_index=thread.data.player.index,element={name=name}}
|
||||
left.open(fake_event)
|
||||
end
|
||||
end
|
||||
end):queue()
|
||||
end):open()
|
||||
end
|
||||
end
|
||||
|
||||
--- Used to open the left gui of every player
|
||||
-- @usage Gui.left.open('foo')
|
||||
-- @tparam string left_name this is the gui that you want to open
|
||||
function left.open(left_name)
|
||||
local _left = Gui._get_data('left')[left_name]
|
||||
if not _left then return end
|
||||
if not Server or not Server._thread then
|
||||
for _,player in pairs(game.connected_players) do
|
||||
local left_flow = mod_gui.get_frame_flow(player)
|
||||
if left_flow[_left.name] then left_flow[_left.name].style.visible = true end
|
||||
end
|
||||
else
|
||||
Server.new_thread{
|
||||
data={players=game.connected_players}
|
||||
}:on_event('tick',function(thread)
|
||||
if #thread.data.players == 0 then thread:close() return end
|
||||
local player = table.remove(thread.data.players,1)
|
||||
local left_flow = mod_gui.get_frame_flow(player)
|
||||
if left_flow[_left.name] then left_flow[_left.name].style.visible = true end
|
||||
end):open()
|
||||
end
|
||||
end
|
||||
|
||||
--- Used to close the left gui of every player
|
||||
-- @usage Gui.left.close('foo')
|
||||
-- @tparam string left_name this is the gui that you want to close
|
||||
function left.close(left_name)
|
||||
local _left = Gui._get_data('left')[left_name]
|
||||
if not _left then return end
|
||||
if not Server or not Server._thread then
|
||||
for _,player in pairs(game.connected_players) do
|
||||
local left_flow = mod_gui.get_frame_flow(player)
|
||||
if left_flow[_left.name] then left_flow[_left.name].style.visible = false end
|
||||
end
|
||||
else
|
||||
Server.new_thread{
|
||||
data={players=game.connected_players}
|
||||
}:on_event('tick',function(thread)
|
||||
if #thread.data.players == 0 then thread:close() return end
|
||||
local player = table.remove(thread.data.players,1)
|
||||
local left_flow = mod_gui.get_frame_flow(player)
|
||||
if left_flow[_left.name] then left_flow[_left.name].style.visible = false end
|
||||
end):open()
|
||||
end
|
||||
end
|
||||
|
||||
-- this is used to draw the gui for the first time (these guis are never destoryed), used by the script
|
||||
function left._left.open(event)
|
||||
local player = Game.get_player(event)
|
||||
local _left = Gui._get_data('left')[event.element.name]
|
||||
local left_flow = mod_gui.get_frame_flow(player)
|
||||
local frame = nil
|
||||
if left_flow[_left.name] then
|
||||
frame = left_flow[_left.name]
|
||||
frame.clear()
|
||||
else
|
||||
frame = left_flow.add{type='frame',name=_left.name,style=mod_gui.frame_style,caption=_left.caption,direction='vertical'}
|
||||
frame.style.visible = false
|
||||
if is_type(_left.open_on_join,'boolean') then frame.style.visible = _left.open_on_join end
|
||||
end
|
||||
if is_type(_left.draw,'function') then _left.draw(frame) else frame.style.visible = false error('No Callback On '.._left.name) end
|
||||
end
|
||||
|
||||
-- this is called when the toolbar button is pressed
|
||||
function left._left.toggle(event)
|
||||
local player = Game.get_player(event)
|
||||
local _left = Gui._get_data('left')[event.element.name]
|
||||
local left_flow = mod_gui.get_frame_flow(player)
|
||||
if not left_flow[_left.name] then _left.open(event) end
|
||||
local left = left_flow[_left.name]
|
||||
local open = false
|
||||
if is_type(_left.can_open,'function') then
|
||||
local success, err = pcall(_left.can_open,player)
|
||||
if not success then error(err)
|
||||
elseif err == true then open = true
|
||||
elseif Gui._global().over_ride_left_can_open then
|
||||
if is_type(Ranking,'table') and Ranking._presets and Ranking._presets().meta.rank_count > 0 then
|
||||
if Ranking.get_rank(player):allowed(_left.name) then open = true
|
||||
else open = {gui.unauthorized} end
|
||||
end
|
||||
else open = err end
|
||||
else
|
||||
if is_type(Ranking,'table') and Ranking._presets and Ranking._presets().meta.rank_count > 0 then
|
||||
if Ranking.get_rank(player):allowed(_left.name) then open = true
|
||||
else open = {gui.unauthorized} end
|
||||
end
|
||||
end
|
||||
if open == true and left.style.visible ~= true then
|
||||
left.style.visible = true
|
||||
else
|
||||
left.style.visible = false
|
||||
end
|
||||
if open == false then player_return({'gui.cant-open-no-reason'},defines.textcolor.crit,player) player.play_sound{path='utility/cannot_build'}
|
||||
elseif open ~= true then player_return({'gui.cant-open',open},defines.textcolor.crit,player) player.play_sound{path='utility/cannot_build'} end
|
||||
end
|
||||
|
||||
-- draws the left guis when a player first joins, fake_event is just because i am lazy
|
||||
Event.register(defines.events.on_player_joined_game,function(event)
|
||||
local player = Game.get_player(event)
|
||||
local frames = Gui._get_data('left') or {}
|
||||
for name,left in pairs(frames) do
|
||||
local fake_event = {player_index=player.index,element={name=name}}
|
||||
left.open(fake_event)
|
||||
end
|
||||
end)
|
||||
|
||||
return left
|
||||
112
modules/ExpGamingCore/Gui/GuiParts/popup.lua
Normal file
112
modules/ExpGamingCore/Gui/GuiParts/popup.lua
Normal file
@@ -0,0 +1,112 @@
|
||||
--[[
|
||||
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
|
||||
]]
|
||||
|
||||
local popup = {}
|
||||
popup._popup = {}
|
||||
|
||||
function popup._load()
|
||||
popup._popup.close = Gui.inputs.add{
|
||||
type='button',
|
||||
name='popup-close',
|
||||
caption='utility/set_bar_slot',
|
||||
tooltip='Close This Popup'
|
||||
}:on_event('click',function(event)
|
||||
local frame = event.element.parent
|
||||
if frame and frame.valid then frame.destroy() end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Used to add a popup gui style
|
||||
-- @usage Gui.left.add{name='foo',caption='Foo',draw=function}
|
||||
-- @param obj this is what will be made, needs a name and a draw function(root_frame,data)
|
||||
-- @return the object that is made to... well idk but for the future
|
||||
function popup.add(obj)
|
||||
if not is_type(obj,'table') then return end
|
||||
if not is_type(obj.name,'string') then return end
|
||||
verbose('Created Popup Gui: '..obj.name)
|
||||
setmetatable(obj,{__index=popup._popup})
|
||||
local name = obj.name; obj.name = nil
|
||||
Gui._add_data('popup',name,obj)
|
||||
obj.name = name
|
||||
return obj
|
||||
end
|
||||
|
||||
-- this is used by the script to find the popup flow
|
||||
function popup.flow(player)
|
||||
local player = Game.get_player(player)
|
||||
local flow = mod_gui.get_frame_flow(player).popups or mod_gui.get_frame_flow(player).add{name='popups',type='flow',direction='vertical'}
|
||||
return flow
|
||||
end
|
||||
|
||||
--- Use to open a popup for these players
|
||||
-- @usage Gui.popup.open('ban',nil,{player=1,reason='foo'})
|
||||
-- @tparam string style this is the name you gave to the popup when added
|
||||
-- @param data this is the data that is sent to the draw function
|
||||
-- @tparam[opt=game.connected_players] table players the players to open the popup for
|
||||
function popup.open(style,data,players)
|
||||
local _popup = Gui._get_data('popup')[style]
|
||||
local players = players or game.connected_players
|
||||
local data = data or {}
|
||||
if not _popup then return end
|
||||
if _popup.left then Gui.left.close(_popup.left.name) end
|
||||
if not Server or not Server._thread then
|
||||
for _,player in pairs(players) do
|
||||
local flow = popup.flow(player)
|
||||
local _frame = flow.add{
|
||||
type='frame',
|
||||
direction='horizontal',
|
||||
style=mod_gui.frame_style
|
||||
}
|
||||
local frame = _frame.add{
|
||||
type='frame',
|
||||
name='inner_frame',
|
||||
direction='vertical',
|
||||
style='image_frame'
|
||||
}
|
||||
_popup.close:draw(_frame)
|
||||
if is_type(_popup.draw,'function') then
|
||||
local success, err = pcall(_popup.draw,frame,data)
|
||||
if not success then error(err) end
|
||||
else error('No Draw On Popup '.._popup.name) end
|
||||
end
|
||||
else
|
||||
Server.new_thread{
|
||||
data={players=players,popup=_popup,data=data}
|
||||
}:on_event('tick',function(thread)
|
||||
if #thread.data.players == 0 then thread:close() return end
|
||||
local player = table.remove(thread.data.players,1)
|
||||
local flow = popup.flow(player)
|
||||
local _frame = flow.add{
|
||||
type='frame',
|
||||
direction='horizontal',
|
||||
style=mod_gui.frame_style
|
||||
}
|
||||
local frame = _frame.add{
|
||||
type='frame',
|
||||
name='inner_frame',
|
||||
direction='vertical',
|
||||
style='image_frame'
|
||||
}
|
||||
thread.data.popup.close:draw(_frame)
|
||||
if is_type(thread.data.popup.draw,'function') then
|
||||
local success, err = pcall(thread.data.popup.draw,frame,thread.data.data)
|
||||
if not success then error(err) end
|
||||
else error('No Draw On Popup '..thread.data.popup.name) end
|
||||
end):open()
|
||||
end
|
||||
end
|
||||
|
||||
function popup._popup:add_left(obj)
|
||||
obj.name = obj.name or self.name
|
||||
self.left = Gui.left.add(obj)
|
||||
end
|
||||
|
||||
Event.register(defines.events.on_player_joined_game,popup.flow)
|
||||
|
||||
return popup
|
||||
173
modules/ExpGamingCore/Gui/GuiParts/test.lua
Normal file
173
modules/ExpGamingCore/Gui/GuiParts/test.lua
Normal file
@@ -0,0 +1,173 @@
|
||||
-- this is just testing all the diffrent inputs to open test use /c Gui.test()
|
||||
|
||||
local gui_tset_close = Gui.inputs.add{
|
||||
name='gui-test-close',
|
||||
type='button',
|
||||
caption='Close Test Gui'
|
||||
}:on_event('click',function(event) event.element.parent.destroy() end)
|
||||
|
||||
local caption_test = Gui.inputs.add{
|
||||
name='text-button',
|
||||
type='button',
|
||||
caption='Test'
|
||||
}:on_event('click',function(event) game.print('test') end)
|
||||
|
||||
local sprite_test = Gui.inputs.add{
|
||||
name='sprite-button',
|
||||
type='button',
|
||||
sprite='item/lab'
|
||||
}:on_event('click',function(event) game.print('test') end)
|
||||
|
||||
local input_test = Gui.inputs.add_button('test-inputs','Try RMB','alt,ctrl,shift and mouse buttons',{
|
||||
{
|
||||
function(player,mouse,keys) return mouse == defines.mouse_button_type.left and keys.alt end,
|
||||
function(player,element) player_return('Left: Alt',nil,player) end
|
||||
},
|
||||
{
|
||||
function(player,mouse,keys) return mouse == defines.mouse_button_type.left and keys.ctrl end,
|
||||
function(player,element) player_return('Left: Ctrl',nil,player) end
|
||||
},
|
||||
{
|
||||
function(player,mouse,keys) return mouse == defines.mouse_button_type.left and keys.shift end,
|
||||
function(player,element) player_return('Left: Shift',nil,player) end
|
||||
},
|
||||
{
|
||||
function(player,mouse,keys) return mouse == defines.mouse_button_type.right and keys.alt end,
|
||||
function(player,element) player_return('Right: Alt',nil,player) end
|
||||
},
|
||||
{
|
||||
function(player,mouse,keys) return mouse == defines.mouse_button_type.right and keys.ctrl end,
|
||||
function(player,element) player_return('Right: Ctrl',nil,player) end
|
||||
},
|
||||
{
|
||||
function(player,mouse,keys) return mouse == defines.mouse_button_type.right and keys.shift end,
|
||||
function(player,element) player_return('Right: Shift',nil,player) end
|
||||
}
|
||||
}):on_event('error',function(err) game.print('this is error handliling') end)
|
||||
|
||||
local elem_test = Gui.inputs.add_elem_button('test-elem','item','Testing Elems',function(player,element,elem)
|
||||
player_return(elem.type..' '..elem.value,nil,player)
|
||||
end)
|
||||
|
||||
local check_test = Gui.inputs.add_checkbox('test-check',false,'Cheat Mode',function(player,parent)
|
||||
return game.players[parent.player_index].cheat_mode
|
||||
end,function(player,element)
|
||||
player.cheat_mode = true
|
||||
end,function(player,element)
|
||||
player.cheat_mode = false
|
||||
end)
|
||||
|
||||
local radio_test = Gui.inputs.add_checkbox('test-radio',true,'Kill Self',function(player,parent)
|
||||
return false
|
||||
end,function(player,element)
|
||||
if player.character then player.character.die() end
|
||||
Gui.inputs.reset_radio(element.parent['test-radio-reset'])
|
||||
end)
|
||||
|
||||
local radio_test_reset = Gui.inputs.add_checkbox('test-radio-reset',true,'Reset Kill Self',function(player,parent)
|
||||
return not parent['test-radio'].state
|
||||
end,function(player,element)
|
||||
Gui.inputs.reset_radio(element.parent['test-radio'])
|
||||
end)
|
||||
|
||||
local text_test = Gui.inputs.add_text('test-text',false,'default text',function(player,text,element)
|
||||
player_return(text,nil,player)
|
||||
end)
|
||||
|
||||
local box_test = Gui.inputs.add_text('test-box',true,'default text but a box',function(player,text,element)
|
||||
player_return(text,nil,player)
|
||||
end)
|
||||
|
||||
local slider_test = Gui.inputs.add_slider('test-slider','vertical',0,5,function(player,parent)
|
||||
return player.character_running_speed_modifier
|
||||
end,function(player,value,percent,element)
|
||||
player.character_running_speed_modifier = value
|
||||
player_return('Value In Percent of Max '..math.floor(percent*100)-(math.floor(percent*100)%5),nil,player)
|
||||
end)
|
||||
|
||||
local drop_test = Gui.inputs.add_drop_down('test-drop',table.keys(defines.color),1,function(player,selected,items,element)
|
||||
player.color = defines.color[selected]
|
||||
player.chat_color = defines.color[selected]
|
||||
end)
|
||||
|
||||
local function test_gui(event)
|
||||
if not game.player and not event.player_index then return end
|
||||
local player = game.player or Game.get_player(event)
|
||||
if mod_gui.get_frame_flow(player)['gui-test'] then mod_gui.get_frame_flow(player)['gui-test'].destroy() end
|
||||
local frame = mod_gui.get_frame_flow(player).add{type='frame',name='gui-test',direction='vertical'}
|
||||
gui_tset_close:draw(frame)
|
||||
caption_test:draw(frame)
|
||||
sprite_test:draw(frame)
|
||||
input_test:draw(frame)
|
||||
elem_test:draw(frame)
|
||||
check_test:draw(frame)
|
||||
radio_test:draw(frame)
|
||||
radio_test_reset:draw(frame)
|
||||
text_test:draw(frame)
|
||||
box_test:draw(frame)
|
||||
slider_test:draw(frame)
|
||||
drop_test:draw(frame)
|
||||
end
|
||||
|
||||
Gui.toolbar.add('open-gui-test','Open Test Gui','Opens the test gui with every input',test_gui)
|
||||
|
||||
-- testing the center gui
|
||||
Gui.center.add{
|
||||
name='test-center',
|
||||
caption='Gui Center',
|
||||
tooltip='Just a gui test'
|
||||
}:add_tab('tab-1','Tab 1','Just a tab',function(frame)
|
||||
frame.add{type='label',caption='Test'}
|
||||
end):add_tab('tab-2','Tab 2','Just a tab',function(frame)
|
||||
for i = 1,100 do
|
||||
frame.add{type='label',caption='Test 2'}
|
||||
end
|
||||
end)
|
||||
|
||||
-- testing the left gui
|
||||
Gui.left.add{
|
||||
name='test-left',
|
||||
caption='Gui Left',
|
||||
tooltip='just testing',
|
||||
draw=function(frame)
|
||||
for _,player in pairs(game.connected_players) do
|
||||
frame.add{type='label',caption=player.name}
|
||||
end
|
||||
end,
|
||||
can_open=function(player) return player.index == 1 end
|
||||
}
|
||||
|
||||
local text_popup = Gui.inputs.add_text('test-popup-text',true,'Message To Send',function(player,text,element)
|
||||
element.text = text
|
||||
end)
|
||||
local send_popup = Gui.inputs.add{
|
||||
type='button',
|
||||
name='test-popup-send',
|
||||
caption='Send Message'
|
||||
}:on_event('click',function(event)
|
||||
local player = Game.get_player(event)
|
||||
local message = event.element.parent['test-popup-text'].text
|
||||
Gui.popup.open('test-popup',{player=player.name,message=message})
|
||||
end)
|
||||
Gui.popup.add{
|
||||
name='test-popup',
|
||||
caption='Gui Popup',
|
||||
draw=function(frame,data)
|
||||
frame.add{type='label',caption='Opened by: '..data.player}
|
||||
frame.add{type='label',caption='Message: '..data.message}
|
||||
end
|
||||
}:add_left{
|
||||
caption='Gui Left w/ Popup',
|
||||
tooltip='Send a message',
|
||||
draw=function(frame)
|
||||
text_popup:draw(frame)
|
||||
send_popup:draw(frame)
|
||||
end
|
||||
}
|
||||
|
||||
return test_gui
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
51
modules/ExpGamingCore/Gui/GuiParts/toolbar.lua
Normal file
51
modules/ExpGamingCore/Gui/GuiParts/toolbar.lua
Normal file
@@ -0,0 +1,51 @@
|
||||
--[[
|
||||
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
|
||||
]]
|
||||
|
||||
local toolbar = {}
|
||||
|
||||
--- Add a button to the toolbar, ranks need to be allowed to use these buttons if ranks is preset
|
||||
-- @usage toolbar.add('foo','Foo','Test',function() game.print('test') end)
|
||||
-- @tparam string name the name of the button
|
||||
-- @tparam string caption can be a sprite path or text to show
|
||||
-- @tparam string tooltip the help to show for the button
|
||||
-- @tparam function callback the function which is called on_click
|
||||
-- @treturn table the button object that was made
|
||||
function toolbar.add(name,caption,tooltip,callback)
|
||||
verbose('Created Toolbar Button: '..name)
|
||||
local button = Gui.inputs.add{type='button',name=name,caption=caption,tooltip=tooltip}
|
||||
button:on_event(Gui.inputs.events.click,callback)
|
||||
Gui._add_data('toolbar',name,button)
|
||||
return button
|
||||
end
|
||||
|
||||
--- Draws the toolbar for a certain player
|
||||
-- @usage toolbar.draw(1)
|
||||
-- @param player the player to draw the tool bar of
|
||||
function toolbar.draw(player)
|
||||
local player = Game.get_player(player)
|
||||
if not player then return end
|
||||
local toolbar_frame = mod_gui.get_button_flow(player)
|
||||
toolbar_frame.clear()
|
||||
if not Gui._get_data('toolbar') then return end
|
||||
for name,button in pairs(Gui._get_data('toolbar')) do
|
||||
if is_type(Ranking,'table') and Ranking._presets and Ranking._presets().meta.rank_count > 0 then
|
||||
local rank = Ranking.get_rank(player)
|
||||
if rank:allowed(name) then
|
||||
button:draw(toolbar_frame)
|
||||
end
|
||||
else button:draw(toolbar_frame) end
|
||||
end
|
||||
end
|
||||
|
||||
if defines.events.rank_change then
|
||||
Event.register(defines.events.rank_change,toolbar.draw)
|
||||
end
|
||||
Event.register(defines.events.on_player_joined_game,toolbar.draw)
|
||||
|
||||
return toolbar
|
||||
188
modules/ExpGamingCore/Gui/control.lua
Normal file
188
modules/ExpGamingCore/Gui/control.lua
Normal file
@@ -0,0 +1,188 @@
|
||||
--[[
|
||||
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
|
||||
]]
|
||||
|
||||
local Gui = {}
|
||||
local Gui_data = {}
|
||||
|
||||
-- only really used when parts of expcore are missing, or script debuging (ie to store the location of frames)
|
||||
function Gui._global(reset)
|
||||
global.exp_core = not reset and global.exp_core or {}
|
||||
global.exp_core.gui = not reset and global.exp_core.gui or {}
|
||||
return global.exp_core.gui
|
||||
end
|
||||
|
||||
-- this is to enforce the read only propetry of the gui
|
||||
function Gui._add_data(key,value_key,value)
|
||||
if game then return end
|
||||
if not Gui_data[key] then Gui_data[key] = {} end
|
||||
Gui_data[key][value_key] = value
|
||||
end
|
||||
|
||||
function Gui._get_data(key) return Gui_data[key] end
|
||||
|
||||
Gui.center = require(module_path..'/GuiParts/center')
|
||||
Gui.inputs = require(module_path..'/GuiParts/inputs')
|
||||
Gui.left = require(module_path..'/GuiParts/left')
|
||||
Gui.popup = require(module_path..'/GuiParts/popup')
|
||||
Gui.toolbar = require(module_path..'/GuiParts/toolbar')
|
||||
|
||||
--- Add a white bar to any gui frame
|
||||
-- @usage Gui.bar(frame,100)
|
||||
-- @param frame the frame to draw the line to
|
||||
-- @param[opt=10] width the width of the bar
|
||||
-- @return the line that was made type is progressbar
|
||||
function Gui.bar(frame,width)
|
||||
local line = frame.add{
|
||||
type='progressbar',
|
||||
size=1,
|
||||
value=1
|
||||
}
|
||||
line.style.height = 3
|
||||
line.style.width = width or 10
|
||||
line.style.color = defines.color.white
|
||||
return line
|
||||
end
|
||||
|
||||
--- Used to set the index of a drop down to a certian item
|
||||
-- @usage Gui.set_dropdown_index(dropdown,player.name)
|
||||
-- @param dropdown the dropdown that is to be effected
|
||||
-- @param _item this is the item to look for
|
||||
-- @return returns the dropdown if it was successful
|
||||
function Gui.set_dropdown_index(dropdown,_item)
|
||||
if dropdown and dropdown.valid and dropdown.items and _item then else return end
|
||||
local _index = 1
|
||||
for index, item in pairs(dropdown.items) do
|
||||
if item == _item then _index = index break end
|
||||
end
|
||||
dropdown.selected_index = _index
|
||||
return dropdown
|
||||
end
|
||||
|
||||
Gui.on_init=function(self)
|
||||
Gui.test = require(module_path..'/GuiParts/test')
|
||||
if not Server then return end
|
||||
Event.register(-1,function(event)
|
||||
Server.new_thread{
|
||||
name='camera-follow',
|
||||
data={cams={},cam_index=1,players={}}
|
||||
}:on_event('tick',function(self)
|
||||
local _cam = self.data.cams[self.data.cam_index]
|
||||
if not _cam then self.data.cam_index = 1 _cam = self.data.cams[self.data.cam_index] end
|
||||
if not _cam then return end
|
||||
if not _cam.cam.valid then table.remove(self.data.cams,self.data.cam_index)
|
||||
elseif not _cam.entity.valid then table.remove(self.data.cams,self.data.cam_index)
|
||||
else _cam.cam.position = _cam.entity.position if not _cam.surface then _cam.cam.surface_index = _cam.entity.surface.index end self.data.cam_index = self.data.cam_index+1
|
||||
end
|
||||
end):on_event('error',function(self,err)
|
||||
-- posible error handling if needed
|
||||
error(err)
|
||||
end):on_event(defines.events.on_player_respawned,function(self,event)
|
||||
if self.data.players[event.player_index] then
|
||||
local remove = {}
|
||||
for index,cam in pairs(self.data.players[event.player_index]) do
|
||||
Gui.cam_link{cam=cam,entity=Game.get_player(event).character}
|
||||
if not cam.valid then table.insert(remove,index) end
|
||||
end
|
||||
for _,index in pairs(remove) do
|
||||
table.remove(self.data.players[event.player_index],index)
|
||||
end
|
||||
end
|
||||
end):open()
|
||||
end)
|
||||
end
|
||||
|
||||
--- Adds a camera that updates every tick (or less depeading on how many are opening) it will move to follow an entity
|
||||
-- @usage Gui.cam_link{entity=game.player.character,frame=frame,width=50,hight=50,zoom=1}
|
||||
-- @usage Gui.cam_link{entity=game.player.character,cam=frame.camera,surface=game.surfaces['testing']}
|
||||
-- @tparam table data contains all other params given below
|
||||
-- @field entity this is the entity that the camera will follow
|
||||
-- @field cam a camera that you already have in the gui
|
||||
-- @field frame the frame to add the camera to, no effect if cam param is given
|
||||
-- @field zoom the zoom to give the new camera
|
||||
-- @field width the width to give the new camera
|
||||
-- @field height the height to give the new camera
|
||||
-- @field surface this will over ride the surface that the camera follows on, allowing for a 'ghost surface' while keeping same position
|
||||
-- @field respawn_open if set to true then the camera will auto re link to the player after a respawn
|
||||
-- @return the camera that the function used be it made or given as a param
|
||||
function Gui.cam_link(data)
|
||||
if not data.entity or not data.entity.valid then return end
|
||||
if is_type(data.cam,'table') and data.cam.__self and data.cam.valid then
|
||||
data.cam = data.cam
|
||||
elseif data.frame then
|
||||
data.cam={}
|
||||
data.cam.type='camera'
|
||||
data.cam.name='camera'
|
||||
data.cam.position= data.entity.position
|
||||
data.cam.surface_index= data.surface and data.surface.index or data.entity.surface.index
|
||||
data.cam.zomm = data.zoom
|
||||
data.cam = data.frame.add(data.cam)
|
||||
data.cam.style.width = data.width or 100
|
||||
data.cam.style.height = data.height or 100
|
||||
else return end
|
||||
if not Server or not Server._thread or not Server.get_thread('camera-follow') then
|
||||
if not Gui._global().cams then
|
||||
Gui._global().cams = {}
|
||||
Gui._global().cam_index = 1
|
||||
end
|
||||
if data.cam then
|
||||
local surface = data.surface and data.surface.index or nil
|
||||
table.insert(Gui._global().cams,{cam=data.cam,entity=data.entity,surface=surface})
|
||||
end
|
||||
if not Gui._global().players then
|
||||
Gui._global().players = {}
|
||||
end
|
||||
if data.respawn_open then
|
||||
if data.entity.player then
|
||||
if not Gui._global().players[data.entity.player.index] then Gui._global().players[data.entity.player.index] = {} end
|
||||
table.insert(Gui._global().players[data.entity.player.index],data.cam)
|
||||
end
|
||||
end
|
||||
else
|
||||
local thread = Server.get_thread('camera-follow')
|
||||
local surface = data.surface and data.surface.index or nil
|
||||
table.insert(thread.data.cams,{cam=data.cam,entity=data.entity,surface=surface})
|
||||
if data.respawn_open then
|
||||
if data.entity.player then
|
||||
if not thread.data.players[data.entity.player.index] then thread.data.players[data.entity.player.index] = {} end
|
||||
table.insert(thread.data.players[data.entity.player.index],data.cam)
|
||||
end
|
||||
end
|
||||
end
|
||||
return data.cam
|
||||
end
|
||||
|
||||
Event.register(defines.events.on_tick, function(event)
|
||||
if Gui.left and ((event.tick+10)/(3600*game.speed)) % 15 == 0 then
|
||||
Gui.left.update()
|
||||
end
|
||||
if Gui._global().cams and is_type(Gui._global().cams,'table') and #Gui._global().cams > 0 then
|
||||
local _cam = Gui._global().cams[Gui._global().cam_index]
|
||||
if not _cam then Gui._global().cam_index = 1 _cam = Gui._global().cams[Gui._global().cam_index] end
|
||||
if not _cam then return end
|
||||
if not _cam.cam.valid then table.remove(Gui._global().cams,Gui._global().cam_index)
|
||||
elseif not _cam.entity.valid then table.remove(Gui._global().cams,Gui._global().cam_index)
|
||||
else _cam.cam.position = _cam.entity.position if not _cam.surface then _cam.cam.surface_index = _cam.entity.surface.index end Gui._global().cam_index = Gui._global().cam_index+1
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Event.register(defines.events.on_player_respawned,function(event)
|
||||
if Gui._global().players and is_type(Gui._global().players,'table') and #Gui._global().players > 0 and Gui._global().players[event.player_index] then
|
||||
local remove = {}
|
||||
for index,cam in pairs(Gui._global().players[event.player_index]) do
|
||||
Gui.cam_link{cam=cam,entity=Game.get_player(event).character}
|
||||
if not cam.valid then table.insert(remove,index) end
|
||||
end
|
||||
for _,index in pairs(remove) do
|
||||
table.remove(Gui._global().players[event.player_index],index)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
return Gui
|
||||
230
modules/ExpGamingCore/Ranking/base_ranks.lua
Normal file
230
modules/ExpGamingCore/Ranking/base_ranks.lua
Normal file
@@ -0,0 +1,230 @@
|
||||
--[[
|
||||
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-----------------------------------------------------------
|
||||
local groups = {}
|
||||
local ranks = {}
|
||||
|
||||
function Ranking._add_group(group) if game then return end table.insert(groups,group) end
|
||||
function Ranking._add_rank(rank,pos) if game then return end if pos then table.insert(ranks,pos,rank) else table.insert(ranks,rank) end end
|
||||
function Ranking._set_rank_power() if game then return end for power,rank in pairs(ranks) do rank.power = power end end
|
||||
function Ranking._update_rank(rank) if game then return end ranks[rank.power] = rank end
|
||||
function Ranking._update_group(group) if game then return end groups[group.index] = group 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, lower is better
|
||||
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
|
||||
-- Ranks will inherite from each other ie higher ranks can do everything lower ranks can
|
||||
-- But groups do not inherite from each other
|
||||
-- DO NOT REMOVE ANY OF THESE GROUPS
|
||||
|
||||
local root = Ranking._group:create{
|
||||
name='Root',
|
||||
allow={
|
||||
['interface'] = true
|
||||
},
|
||||
disallow={}
|
||||
}
|
||||
local admin = Ranking._group:create{
|
||||
name='Admin',
|
||||
allow={},
|
||||
disallow={
|
||||
'set_allow_commands',
|
||||
'edit_permission_group',
|
||||
'delete_permission_group',
|
||||
'add_permission_group'
|
||||
}
|
||||
}
|
||||
local user = Ranking._group:create{
|
||||
name='User',
|
||||
allow={},
|
||||
disallow={
|
||||
'set_allow_commands',
|
||||
'edit_permission_group',
|
||||
'delete_permission_group',
|
||||
'add_permission_group'
|
||||
}
|
||||
}
|
||||
local jail = Ranking._group:create{
|
||||
name='Jail',
|
||||
allow={},
|
||||
disallow={
|
||||
'set_allow_commands',
|
||||
'edit_permission_group',
|
||||
'delete_permission_group',
|
||||
'add_permission_group',
|
||||
'open_character_gui',
|
||||
'begin_mining',
|
||||
'start_walking',
|
||||
'player_leave_game',
|
||||
'open_blueprint_library_gui',
|
||||
'build_item',
|
||||
'use_item',
|
||||
'select_item',
|
||||
'rotate_entity',
|
||||
'open_train_gui',
|
||||
'open_train_station_gui',
|
||||
'open_gui',
|
||||
'open_item',
|
||||
'deconstruct',
|
||||
'build_rail',
|
||||
'cancel_research',
|
||||
'start_research',
|
||||
'set_train_stopped',
|
||||
'select_gun',
|
||||
'open_technology_gui',
|
||||
'open_trains_gui',
|
||||
'edit_custom_tag',
|
||||
'craft',
|
||||
'setup_assembling_machine',
|
||||
}
|
||||
}
|
||||
|
||||
-- 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,
|
||||
is_admin=true,
|
||||
is_spectator=true,
|
||||
base_afk_time=false
|
||||
}
|
||||
|
||||
admin:add_rank{
|
||||
name='Admin',
|
||||
short_hand='Admin',
|
||||
tag='[Admin]',
|
||||
colour={r=233,g=63,b=233},
|
||||
is_admin=true,
|
||||
is_spectator=true,
|
||||
base_afk_time=false
|
||||
}
|
||||
|
||||
user:add_rank{
|
||||
name='Member',
|
||||
short_hand='Mem',
|
||||
tag='[Member]',
|
||||
colour={r=24,g=172,b=188},
|
||||
disallow={
|
||||
'set_auto_launch_rocket',
|
||||
'change_programmable_speaker_alert_parameters',
|
||||
'drop_item'
|
||||
},
|
||||
base_afk_time=60
|
||||
}
|
||||
user:add_rank{
|
||||
name='Guest',
|
||||
short_hand='',
|
||||
tag='',
|
||||
colour={r=255,g=159,b=27},
|
||||
is_default=true,
|
||||
disallow={
|
||||
'build_terrain',
|
||||
'remove_cables',
|
||||
'launch_rocket',
|
||||
'reset_assembling_machine',
|
||||
'cancel_research'
|
||||
},
|
||||
base_afk_time=10
|
||||
}
|
||||
|
||||
jail:add_rank{
|
||||
name='Jail',
|
||||
short_hand='Jail',
|
||||
tag='[Jail]',
|
||||
colour={r=50,g=50,b=50},
|
||||
disallow={},
|
||||
base_afk_time=false
|
||||
}
|
||||
|
||||
function Ranking._auto_edit_ranks()
|
||||
for power,rank in pairs(ranks) do
|
||||
if ranks[power-1] then
|
||||
rank:edit('disallow',false,ranks[power-1].disallow)
|
||||
end
|
||||
end
|
||||
for power = #ranks, 1, -1 do
|
||||
local rank = ranks[power]
|
||||
rank:edit('disallow',false,rank.group.disallow)
|
||||
if ranks[power+1] then
|
||||
rank:edit('allow',false,ranks[power+1].allow)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- 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 = {time_ranks={}}
|
||||
for power,rank in pairs(ranks) do
|
||||
meta.rank_count = power
|
||||
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 rank.time < meta.time_lowest then meta.time_lowest = rank.time end
|
||||
end
|
||||
end
|
||||
return meta
|
||||
end
|
||||
124
modules/ExpGamingCore/Ranking/config_ranks.lua
Normal file
124
modules/ExpGamingCore/Ranking/config_ranks.lua
Normal file
@@ -0,0 +1,124 @@
|
||||
--[[
|
||||
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 reference 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 Assigned by the script to show the highest rank in this group.
|
||||
lowest Assigned by the script to show the lowest rank in this group.
|
||||
How to add ranks:
|
||||
Name What will be used in the scripts and is often the best choice for display in text.
|
||||
short_hand What can be used when short on space but the rank still need to be displayed.
|
||||
tag The tag the player will gain when moved to the rank, it can be nil.
|
||||
time Used for auto-rank feature where you are moved to the rank after a certain play time in minutes.
|
||||
colour The RGB value that can be used to emphasise GUI elements based on rank.
|
||||
power Assigned by the script based on their index in ranks, you can insert new ranks between current ones.
|
||||
group Assigned by the script to show the group this rank is in.
|
||||
disallow A list containing input actions that the user can not perform.
|
||||
allow A list of custom commands and effects that that rank can use, all defined in the scripts.
|
||||
|
||||
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.
|
||||
|
||||
local groups = Ranking._groups(true)
|
||||
|
||||
groups['Root']:edit('allow',false,{
|
||||
['testing']=true
|
||||
})
|
||||
|
||||
groups['Root']:add_rank{
|
||||
name='Owner',
|
||||
short_hand='Owner',
|
||||
tag='[Owner]',
|
||||
time=nil,
|
||||
colour={r=170,g=0,b=0},
|
||||
is_admin = true,
|
||||
is_spectator=true,
|
||||
base_afk_time=false
|
||||
}
|
||||
groups['Root']:add_rank{
|
||||
name='Community Manager',
|
||||
short_hand='Com Mngr',
|
||||
tag='[Com Mngr]',
|
||||
colour={r=150,g=68,b=161},
|
||||
is_admin = true,
|
||||
is_spectator=true,
|
||||
base_afk_time=false
|
||||
}
|
||||
groups['Root']:add_rank{
|
||||
name='Developer',
|
||||
short_hand='Dev',
|
||||
tag='[Dev]',
|
||||
colour={r=179,g=125,b=46},
|
||||
is_admin = true,
|
||||
is_spectator=true,
|
||||
base_afk_time=false
|
||||
}
|
||||
|
||||
groups['Admin']:add_rank{
|
||||
name='Mod',
|
||||
short_hand='Mod',
|
||||
tag='[Mod]',
|
||||
colour={r=0,g=170,b=0},
|
||||
disallow={
|
||||
'server_command'
|
||||
},
|
||||
is_admin = true,
|
||||
is_spectator=true,
|
||||
base_afk_time=false
|
||||
}
|
||||
|
||||
groups['User']:add_rank{
|
||||
name='Donator',
|
||||
short_hand='P2W',
|
||||
tag='[P2W]',
|
||||
colour={r=233,g=63,b=233},
|
||||
power=0,
|
||||
is_spectator=true,
|
||||
base_afk_time=120
|
||||
}
|
||||
groups['User']:add_rank{
|
||||
name='Veteran',
|
||||
short_hand='Vet',
|
||||
tag='[Veteran]',
|
||||
time=600,
|
||||
colour={r=140,g=120,b=200},
|
||||
power=1,
|
||||
base_afk_time=60
|
||||
}
|
||||
groups['User']:add_rank{
|
||||
name='Regular',
|
||||
short_hand='Reg',
|
||||
tag='[Regular]',
|
||||
time=180,
|
||||
colour={r=24,g=172,b=188},
|
||||
power=3,
|
||||
base_afk_time=30
|
||||
}
|
||||
|
||||
local ranks = Ranking._ranks(true)
|
||||
|
||||
ranks['Root']:edit('test',true,'testing')
|
||||
|
||||
Ranking._base_preset{
|
||||
['badgamernl']='Owner',
|
||||
['arty714']='Community Manager',
|
||||
['cooldude2606']='Developer',
|
||||
['mark9064']='Admin'
|
||||
}
|
||||
392
modules/ExpGamingCore/Ranking/control.lua
Normal file
392
modules/ExpGamingCore/Ranking/control.lua
Normal file
@@ -0,0 +1,392 @@
|
||||
--[[
|
||||
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-----------------------------------------------------------
|
||||
local Ranking = {}
|
||||
defines.events.rank_change = script.generate_event_name()
|
||||
Ranking._rank = {}
|
||||
Ranking._group = {}
|
||||
-- this is just for debuging when setting you rank powers
|
||||
function Ranking.output_ranks(player)
|
||||
local player = Game.get_player(player) or game.player or nil
|
||||
if not player then return end
|
||||
for power,rank in pairs(Ranking._ranks()) do
|
||||
local output = power..') '..rank.name
|
||||
output=output..' '..rank.tag
|
||||
local admin = 'No'; if rank.is_root then admin = 'Root' elseif rank.is_admin then admin = 'Yes' end
|
||||
output=output..' Admin: '..admin
|
||||
output=output..' Group: '..rank.group.name
|
||||
output=output..' AFK: '..tostring(rank.base_afk_time)
|
||||
player_return(output,rank.colour,player)
|
||||
end
|
||||
end
|
||||
|
||||
-- this function is to avoid errors - see /ranks.lua
|
||||
function Ranking._ranks(names)
|
||||
return {}
|
||||
end
|
||||
|
||||
-- this function is to avoid errors - see /ranks.lua
|
||||
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(table)
|
||||
Ranking._presets().current = table
|
||||
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={},last_jail=nil} 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)
|
||||
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 nil
|
||||
else
|
||||
_return = mixed.group and mixed or nil
|
||||
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_rank(Ranking._presets().meta.root)
|
||||
or string.contains(mixed,'root') and Ranking.get_rank(Ranking._presets().meta.root)
|
||||
or nil
|
||||
end
|
||||
return _return
|
||||
end
|
||||
|
||||
--- Returns the group object used to sort ranks given group name or see Ranking.get_rank
|
||||
-- @usage Ranking.get_group(game.player)
|
||||
-- Ranking.get_group('root')
|
||||
-- @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)
|
||||
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 table.autokey(groups,mixed) and table.autokey(groups,mixed)
|
||||
or false
|
||||
end
|
||||
|
||||
--- Prints to all rank of greater/lower power of the rank given
|
||||
-- @usage Ranking.print('admin','We got a grifer')
|
||||
-- @param rank_base the rank that acts as the cut off point (rank is always included)
|
||||
-- @param rtn what do you want to return to the players
|
||||
-- @tparam defines.color colour the colour that will be used to print
|
||||
-- @tparam bolean below if true rank below base are printed to
|
||||
function Ranking.print(rank_base,rtn,colour,below)
|
||||
local colour = colour or defines.color.white
|
||||
local rank_base = Ranking.get_rank(rank_base)
|
||||
local ranks = Ranking._ranks()
|
||||
if below then
|
||||
for power,rank in pairs(ranks) do
|
||||
if rank_base.power <= power then rank:print(rtn,colour,true) end
|
||||
end
|
||||
else
|
||||
for power,rank in pairs(ranks) do
|
||||
if rank_base.power >= power then rank:print(rtn,colour) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Gives a user a rank
|
||||
-- @usage Ranking.give_rank(1,'admin')
|
||||
-- @param player the player to give the rank to
|
||||
-- @param rank the rank to give to the player
|
||||
-- @param[opt='server'] by_player the player who is giving the rank
|
||||
-- @param[opt=game.tick] tick the tick that the rank is being given on
|
||||
function Ranking.give_rank(player,rank,by_player,tick)
|
||||
local print_colour = defines.textcolor.info
|
||||
local tick = tick or game.tick
|
||||
local by_player_name = Game.get_player(by_player) and Game.get_player(by_player).name or game.player and game.player.name or is_type(by_player,'string') and by_player or 'server'
|
||||
local rank = Ranking.get_rank(rank) or Ranking.get_rank(Ranking._presets().meta.default)
|
||||
local player = Game.get_player(player) or error('No Player To Give Rank')
|
||||
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' player.play_sound{path='utility/achievement_unlocked'}
|
||||
else player.play_sound{path='utility/game_lost'} end
|
||||
if player.online_time > 60 or by_player_name ~= 'server' then game.print({message,player.name,rank.name,by_player_name},print_colour) end
|
||||
if rank.group.name ~= 'User' then player_return({'ranking.rank-given',rank.name},print_colour,player) end
|
||||
if player.tag ~= old_rank.tag then player_return({'ranking.tag-reset'},print_colour,player) end
|
||||
-- rank change
|
||||
player.permission_group = game.permissions.get_group(rank.name)
|
||||
player.tag = rank.tag
|
||||
if old_rank.group.name ~= 'Jail' then Ranking._presets().old[player.index] = old_rank.name end
|
||||
player.admin = rank.is_admin or false
|
||||
player.spectator = rank.is_spectator or false
|
||||
if defines.events.rank_change then
|
||||
script.raise_event(defines.events.rank_change,{
|
||||
name=defines.events.rank_change,
|
||||
tick=tick,
|
||||
player_index=player.index,
|
||||
by_player_name=by_player_name,
|
||||
new_rank=rank,
|
||||
old_rank=old_rank
|
||||
})
|
||||
end
|
||||
if rank.group.name == 'Jail' and Ranking._presets().last_jail ~= player.name then
|
||||
Sync.emit_embeded{
|
||||
title='Player Jail',
|
||||
color=Color.to_hex(defines.textcolor.med),
|
||||
description='There was a player jailed.',
|
||||
['Player:']=player.name,
|
||||
['By:']='<<inline>>'..by_player_name,
|
||||
['Reason:']='No Reason'
|
||||
}
|
||||
end
|
||||
game.write_file('ranking-change.json',
|
||||
table.json({
|
||||
tick=tick,
|
||||
play_time=player.online_time,
|
||||
player_name=player.name,
|
||||
by_player_name=by_player_name,
|
||||
new_rank=rank.name,
|
||||
old_rank=old_rank.name,
|
||||
power_increase=(old_rank.power-rank.power)
|
||||
})..'\n'
|
||||
, true, 0)
|
||||
end
|
||||
|
||||
--- Revert the last change to a players rank
|
||||
-- @usage Ranking.revert(1)
|
||||
-- @param player the player to revert the rank of
|
||||
-- @param[opt=nil] by_player the player who is doing the revert
|
||||
function Ranking.revert(player,by_player)
|
||||
local player = Game.get_player(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] number 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)])
|
||||
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 = current_rank
|
||||
for _,rank in pairs(ranks) do
|
||||
if rank.power < _rank.power or _rank.power == -1 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
|
||||
|
||||
--- 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.allow[action] or self.is_root or false
|
||||
end
|
||||
|
||||
--- Get all the players in this rank
|
||||
-- @usage rank:get_players()
|
||||
-- @tparam bolean online get only online players
|
||||
-- @treturn table a table of all players in this rank
|
||||
function Ranking._rank:get_players(online)
|
||||
local players = game.permissions.get_group(self.name).players
|
||||
local _return = {}
|
||||
if online then
|
||||
for _,player in pairs(players) do
|
||||
if player.connected then table.insert(_return,player) end
|
||||
end
|
||||
else
|
||||
_return = players
|
||||
end
|
||||
return _return
|
||||
end
|
||||
|
||||
--- Print a message to all players of this rank
|
||||
-- @usage rank:print('foo')
|
||||
-- @param rtn any value you want to return
|
||||
-- @tparam define.color colour the colour that will be used to print
|
||||
-- @tparam boolean show_default weather to use the default rank name for the print
|
||||
function Ranking._rank:print(rtn,colour,show_default)
|
||||
local colour = colour or defines.color.white
|
||||
local meta_data = Ranking._presets().meta
|
||||
local default = Ranking.get_rank(meta_data.default)
|
||||
if not Server or not Server._thread then
|
||||
for _,player in pairs(self:get_players(true)) do
|
||||
if self.name == default.name or show_default then
|
||||
player_return({'ranking.all-rank-print',rtn},colour,player)
|
||||
else
|
||||
player_return({'ranking.rank-print',self.name,rtn},colour,player)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- using threads to make less lag
|
||||
Server.new_thread{
|
||||
data={rank=self,rtn=rtn,default=default.name,all=show_default}
|
||||
}:on_event('resolve',function(thread)
|
||||
return thread.data.rank:get_players(true)
|
||||
end):on_event('success',function(thread,players)
|
||||
for _,player in pairs(players) do
|
||||
if thread.data.rank.name == thread.data.default or thread.data.all then
|
||||
player_return({'ranking.all-rank-print',thread.data.rtn},colour,player)
|
||||
else
|
||||
player_return({'ranking.rank-print',thread.data.rank.name,thread.data.rtn},colour,player)
|
||||
end
|
||||
end
|
||||
end):queue()
|
||||
end
|
||||
end
|
||||
|
||||
-- this is used to edit a group once made key is what is being edited and set_value makes it over ride the current value
|
||||
-- see Addons/playerRanks for examples
|
||||
function Ranking._rank:edit(key,set_value,value)
|
||||
if game then return end
|
||||
verbose('Edited Rank: '..self.name..'/'..key)
|
||||
if set_value then self[key] = value return end
|
||||
if key == 'disallow' then
|
||||
self.disallow = table.merge(self.disallow,value,true)
|
||||
elseif key == 'allow' then
|
||||
self.allow = table.merge(self.allow,value)
|
||||
end
|
||||
Ranking._update_rank(self)
|
||||
end
|
||||
|
||||
-- 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
|
||||
verbose('Created Group: '..obj.name)
|
||||
setmetatable(obj,{__index=Ranking._group})
|
||||
self.index = #Ranking._groups(names)+1
|
||||
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={}}
|
||||
-- if the rank is given power then it is given that place realative to the highest rank in that group,if no power then it is added to the end
|
||||
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
|
||||
verbose('Created Rank: '..obj.name)
|
||||
setmetatable(obj,{__index=Ranking._rank})
|
||||
obj.group = self
|
||||
obj.allow = obj.allow or {}
|
||||
obj.disallow = obj.disallow or {}
|
||||
obj.power = obj.power and self.highest and self.highest.power+obj.power or obj.power or self.lowest and self.lowest.power+1 or nil
|
||||
setmetatable(obj.allow,{__index=self.allow})
|
||||
setmetatable(obj.disallow,{__index=self.disallow})
|
||||
Ranking._add_rank(obj,obj.power)
|
||||
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
|
||||
|
||||
-- this is used to edit a group once made key is what is being edited and set_value makes it over ride the current value
|
||||
-- see Addons/playerRanks for examples
|
||||
function Ranking._group:edit(key,set_value,value)
|
||||
if game then return end
|
||||
verbose('Edited Group: '..self.name..'/'..key)
|
||||
if set_value then self[key] = value return end
|
||||
if key == 'disallow' then
|
||||
self.disallow = table.merge(self.disallow,value,true)
|
||||
elseif key == 'allow' then
|
||||
self.allow = table.merge(self.allow,value)
|
||||
end
|
||||
Ranking._update_group(self)
|
||||
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)
|
||||
|
||||
Event.register(defines.events.on_tick,function(event)
|
||||
if (((event.tick+10)/(3600*game.speed))+(15/2))% 15 == 0 then
|
||||
-- this is the system to auto rank players
|
||||
if not Server or not Server._thread then
|
||||
for _,player in pairs(game.connected_players) do
|
||||
Ranking.find_preset(player,tick)
|
||||
end
|
||||
else
|
||||
Server.new_thread{
|
||||
data={players=game.connected_players}
|
||||
}:on_event('tick',function(thread)
|
||||
if #thread.data.players == 0 then thread:close() return end
|
||||
local player = table.remove(thread.data.players,1)
|
||||
Ranking.find_preset(player,tick)
|
||||
end):open()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Ranking.on_init=function(self)
|
||||
require(module_path.."/base_ranks")
|
||||
require(module_path.."/config_ranks")
|
||||
end
|
||||
|
||||
return Ranking
|
||||
428
modules/ExpGamingCore/Server/control.lua
Normal file
428
modules/ExpGamingCore/Server/control.lua
Normal file
@@ -0,0 +1,428 @@
|
||||
--[[
|
||||
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-----------------------------------------------------------
|
||||
-- server allows control over threads and other features the devs missed out
|
||||
local Server = {}
|
||||
Server._thread = {}
|
||||
|
||||
--- Returns a un-used uuid (better system needed)
|
||||
-- @usage obj.uuid = Server.new_uuid()
|
||||
-- @treturn string the new uuid
|
||||
function Server.new_uuid()
|
||||
local uuid = tostring(Server._uuid()())
|
||||
uuid = string.to_hex('uuid'..uuid)
|
||||
return uuid
|
||||
end
|
||||
|
||||
-- use this to change the location of the server uuids
|
||||
function Server._uuid(reset)
|
||||
global.exp_core = not reset and global.exp_core or {}
|
||||
global.exp_core.uuids = not reset and global.exp_core.uuids or game.create_random_generator()
|
||||
return global.exp_core.uuids
|
||||
end
|
||||
|
||||
--- Returns either the number of threads or a able of threads
|
||||
-- @usage Server.threads() -- return {...}
|
||||
-- Server.threads(true) -- return int
|
||||
-- @tparam[opt=nil] bolean count true to return the number of threads
|
||||
-- @return either a list of threads or a number
|
||||
function Server.threads(count)
|
||||
return count and Server._threads().all._n or Server._threads().all
|
||||
end
|
||||
|
||||
-- use this to change the location of the server threads
|
||||
-- all stores the threads indexed uuid, the other three only store the uuid's to index in the all table
|
||||
function Server._threads(reset)
|
||||
global.exp_core = not reset and global.exp_core or {}
|
||||
global.exp_core.threads = not reset and global.exp_core.threads or {print_to={},queue={},tick={},timeout={},events={},all={_n=0},paused={},named={}}
|
||||
return global.exp_core.threads
|
||||
end
|
||||
|
||||
-- see thread:create (this was done so thread can remain local)
|
||||
function Server.new_thread(obj)
|
||||
return Server._thread:create(obj)
|
||||
end
|
||||
|
||||
--- Used to get a thread via it's uuid or by name if one is given
|
||||
-- @usage Server.get_thread('decon') -- return thread
|
||||
-- @param mixed either a uuid or the name given to a thread
|
||||
-- @treturn table the thread by that name or uuid
|
||||
function Server.get_thread(mixed)
|
||||
local threads = Server._threads()
|
||||
if threads.named[mixed] then return threads.all[threads.named[mixed]]
|
||||
elseif threads.paused[mixed] then return threads.all[threads.paused[mixed]]
|
||||
elseif threads.all[mixed] then return threads.all[mixed]
|
||||
else return false end
|
||||
end
|
||||
|
||||
--- Adds a thread into the resolve queue, can be used to lower lag
|
||||
-- @usage Server.queue_thread(thread) -- return true/false
|
||||
-- @tparam table thread_to_queue the thread to add to the queue must have a resolve function (must be open)
|
||||
-- @treturn boolean was the thread added
|
||||
function Server.queue_thread(thread_to_queue)
|
||||
if not thread_to_queue and not thread_to_queue.valid and not thread_to_queue:valid() then return false end
|
||||
if not thread_to_queue._resolve then return false end
|
||||
table.insert(Server._threads().queue,thread_to_queue.uuid)
|
||||
return true
|
||||
end
|
||||
|
||||
--- Closes all active threads, can use force if it causes errors
|
||||
-- @usage Server.close_all_threads()
|
||||
-- Server.close_all_threads(true) -- use if no force makes errors
|
||||
-- @tparam bolean with_force use force when closing
|
||||
function Server.close_all_threads(with_force)
|
||||
if not with_force then
|
||||
for uuid,next_thread in pairs(Server.threads()) do
|
||||
if uuid ~= '_n' then next_thread:close() end
|
||||
end
|
||||
else
|
||||
Server._threads(true)
|
||||
end
|
||||
end
|
||||
|
||||
--- Runs all the theads which have opened with an on_tick event
|
||||
-- @usage Server.run_tick_threads()
|
||||
function Server.run_tick_threads()
|
||||
table.each(Server._threads().tick,function(uuid)
|
||||
local next_thread = Server.get_thread(uuid)
|
||||
if next_thread and next_thread:valid() and next_thread._tick then
|
||||
local success, err = pcall(next_thread._tick,next_thread)
|
||||
if not success then next_thread:error(err) end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Checks the timeout on all active timeout threads
|
||||
-- @usage Server.check_timeouts()
|
||||
function Server.check_timeouts()
|
||||
table.each(Server._threads().timeout,function(uuid)
|
||||
local next_thread = Server.get_thread(uuid)
|
||||
if next_thread and next_thread:valid() then
|
||||
next_thread:check_timeout()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- for use in debuging
|
||||
function Server._thread_handler_debuger(player,event,state)
|
||||
local player = Game.get_player(player)
|
||||
local print_to = Server._threads().print_to
|
||||
print_to[player.index] = print_to[player.index] or {}
|
||||
print_to[player.index][event] = state
|
||||
end
|
||||
--- Calles all threads on a certain game event (used with script.on_event)
|
||||
-- @tparam table event the event that is called
|
||||
function Server._thread_handler(event)
|
||||
table.each(Server._threads().print_to,function(print_to,player_index,event)
|
||||
if event.name == defines.events.on_tick then return true end
|
||||
if print_to[event.name] then
|
||||
player_return(event,defines.textcolor.bg,player_index)
|
||||
end
|
||||
end,event)
|
||||
local event_id = event.name
|
||||
local threads = Server._threads().events[event_id]
|
||||
if not threads then return end
|
||||
table.each(threads,function(uuid)
|
||||
local next_thread = Server.get_thread(uuid)
|
||||
if next_thread and next_thread:valid() then
|
||||
if is_type(next_thread._events[event_id],'function') then
|
||||
local success, err = pcall(next_thread._events[event_id],next_thread,event)
|
||||
if not success then next_thread:error(err) end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--[[ cant be used V
|
||||
--- Adds a event handler to tell threads about events
|
||||
-- @usage Server.add_thread_handler(defines.event)
|
||||
-- @tparam number event the event to run the thread handler on
|
||||
-- @treturn bolean if the handler was added
|
||||
function Server.add_thread_handler(event)
|
||||
if not is_type(event,'number') then return false end
|
||||
local threads = Server._threads()
|
||||
if not threads.events[event] then
|
||||
threads.events[event] = {}
|
||||
Event.register(event,Server._thread_handler)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
]]
|
||||
|
||||
--- Given a string or function it will run that function and return any values
|
||||
-- @usage Server.interface('local x = 1+1 print(x) return x') -- return 2
|
||||
-- Server.interface('local x = 1+1 print(x)',thread) -- no return
|
||||
-- @param callback either a function or string which will be ran via pcall
|
||||
-- @param[opt] use_thread give a thread for the interface to run on (does not need to be open, but cant use on_resolve)
|
||||
-- @param[opt] ... any args you want to pass to the function
|
||||
function Server.interface(callback,use_thread,...)
|
||||
if use_thread then
|
||||
if use_thread == true then use_thread = Server.new_thread{data={callback,...}} end
|
||||
use_thread:on_event('resolve',function(thread)
|
||||
if is_type(thread.data[1],'function') then
|
||||
local success, err = pcall(unpack(thread.data))
|
||||
if not success then error(err) end
|
||||
return err
|
||||
else
|
||||
local callback = table.remove(thread.data,1)
|
||||
local success, err = pcall(loadstring(callback),unpack(thread.data))
|
||||
if not success then error(err) end
|
||||
return err
|
||||
end
|
||||
end)
|
||||
use_thread:open()
|
||||
Server.queue_thread(use_thread)
|
||||
else
|
||||
if is_type(callback,'function') then
|
||||
local success, err = pcall(callback,...)
|
||||
return success, err
|
||||
else
|
||||
local success, err = pcall(loadstring(callback),...)
|
||||
return success, err
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- thread allows you to run fuinction async to the main game
|
||||
--- Returns a new thread object
|
||||
-- @usage new_thread = thread:create()
|
||||
-- @tparam[opt={}] table obj all are opt {timeout=int,name=str,data=any} advanced users can prefix with _function to avoid the on_function functions
|
||||
-- @treturn table the new thread object
|
||||
function Server._thread:create(obj)
|
||||
local obj = obj or {}
|
||||
setmetatable(obj,{__index=Server._thread})
|
||||
obj.uuid = Server.new_uuid()
|
||||
return obj
|
||||
end
|
||||
|
||||
-- see Server.queue_thread - this just opens it first
|
||||
function Server._thread:queue()
|
||||
self:open()
|
||||
return Server.queue_thread(self)
|
||||
end
|
||||
|
||||
--- Test if the thread has all requied parts
|
||||
-- @usage if thread:valid() then end
|
||||
-- @tparam bolean skip_location_check true to skip the location check
|
||||
-- @treturn bolean is the thread valid
|
||||
function Server._thread:valid(skip_location_check)
|
||||
local skip_location_check = skip_location_check or false
|
||||
if is_type(self.uuid,'string') and
|
||||
skip_location_check or is_type(self.opened,'number') and
|
||||
skip_location_check or is_type(Server._threads().all[self.uuid],'table') and
|
||||
is_type(self.timeout) or is_type(self.timeout,'number') and
|
||||
is_type(self.name) or is_type(self.name,'string') and
|
||||
is_type(self._close) or is_type(self._close,'function') and
|
||||
is_type(self._timeout) or is_type(self._timeout,'function') and
|
||||
is_type(self._tick) or is_type(self._tick,'function') and
|
||||
is_type(self._resolve) or is_type(self._resolve,'function') and
|
||||
is_type(self._success) or is_type(self._success,'function') and
|
||||
is_type(self._error) or is_type(self._error,'function') then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Opens the thread by storing it in a place the server object can find it
|
||||
-- @usage thread:open() -- return true
|
||||
-- @treturn bolean if the thread was opened
|
||||
function Server._thread:open()
|
||||
if not self:valid(true) or self.opened then return false end
|
||||
local threads = Server._threads()
|
||||
local uuid = self.uuid
|
||||
self.opened = game.tick
|
||||
threads.all[uuid] = threads.all[uuid] or self
|
||||
threads.all._n = threads.all._n+1
|
||||
if threads.paused[self.name] then threads.paused[self.name] = nil end
|
||||
if is_type(self.timeout,'number') then table.insert(threads.timeout,uuid) end
|
||||
if is_type(self._tick,'function') then table.insert(threads.tick,uuid) end
|
||||
if is_type(self.name,'string') then threads.named[self.name] = threads.named[self.name] or self.uuid end
|
||||
if is_type(self._events,'table') then
|
||||
table.each(self._events,function(callback,event,threads,uuid)
|
||||
-- cant be used V
|
||||
--Server.add_thread_handler(event)
|
||||
if not threads.events[event] then threads.events[event] = {} end
|
||||
table.insert(threads.events[event],uuid)
|
||||
end,threads,self.uuid)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Inverse of thread:open() - it removes the thread and calles on_close
|
||||
-- @usage thread:close() -- return true
|
||||
-- @treturn bolean if the thread had a on_close function
|
||||
function Server._thread:close()
|
||||
local threads = Server._threads()
|
||||
local uuid = self.uuid
|
||||
local _return = false
|
||||
if is_type(self._close,'function') then pcall(self._close,self) _return = true end
|
||||
local value,key = table.find(threads.queue,function(v,k,uuid) return v == uuid end,uuid)
|
||||
if key then table.remove(threads.queue,key) end
|
||||
local value,key = table.find(threads.timeout,function(v,k,uuid) return v == uuid end,uuid)
|
||||
if key then table.remove(threads.timeout,key) end
|
||||
local value,key = table.find(threads.tick,function(v,k,uuid) return v == uuid end,uuid)
|
||||
if key then table.remove(threads.tick,key) end
|
||||
if is_type(self._events,'table') then
|
||||
table.each(self._events,function(callback,event)
|
||||
if threads.events[event] then
|
||||
local value,key = table.find(threads.events[event],function(v,k,uuid) return v == uuid end,uuid)
|
||||
if key then table.remove(threads.events[event],key) end
|
||||
-- cant be used V
|
||||
--if #threads.events[event] == 0 then Event.remove(event,Server.game_event) threads.events[event] = nil end
|
||||
end
|
||||
end)
|
||||
end
|
||||
self.opened=nil
|
||||
if self.reopen == true then self:open() else
|
||||
if is_type(self.name,'string') then threads.paused[self.name]=self.uuid
|
||||
else threads.all[uuid] = nil threads.all._n = threads.all._n-1 end
|
||||
end
|
||||
return _return
|
||||
end
|
||||
|
||||
--- Trigger the on_resolve function and closes the thread - error and success called based on result of pcall (useful for async)
|
||||
-- @usage thread:resolve(x,y,z) -- return true
|
||||
-- @param[opt] ... any arguments you want to pass to the resolve function
|
||||
-- @treturn bolean true if the thread called on_success or on_error
|
||||
function Server._thread:resolve(...)
|
||||
local _return = false
|
||||
if is_type(self._resolve,'function') then
|
||||
local success, err = pcall(self._resolve,self,...)
|
||||
if success then
|
||||
if is_type(self._success,'function') then
|
||||
Server.interface(function(thread,err)
|
||||
local success,err = pcall(thread._success,thread,err)
|
||||
if not success then thread:error(err) end
|
||||
end,true,self,err)
|
||||
_return = true
|
||||
end
|
||||
else
|
||||
_return = self:error(err)
|
||||
end
|
||||
end
|
||||
self:close()
|
||||
return _return
|
||||
end
|
||||
|
||||
--- Checks the timeout on a thread - if timedout then it calles on_timeout and closes
|
||||
-- @usage thread:check_timeout() -- return true
|
||||
-- @treturn bolean if the thread timedout
|
||||
function Server._thread:check_timeout()
|
||||
local _return = false
|
||||
if not self:valid() then return false end
|
||||
if is_type(self.timeout,'number') and game.tick >= (self.opened+self.timeout) then
|
||||
if is_type(self._timeout,'function') then
|
||||
pcall(self._timeout,self)
|
||||
end
|
||||
_return = true
|
||||
self:close()
|
||||
end
|
||||
return _return
|
||||
end
|
||||
|
||||
--- Rasies an error on this thread
|
||||
-- @usage thread:error(err) -- return true
|
||||
-- @param err the err to be rasied
|
||||
-- @treturn bolean did the thread handdle the error
|
||||
function Server._thread:error(err)
|
||||
local _return = false
|
||||
if is_type(self._error,'function') then
|
||||
pcall(self._error,self,err)
|
||||
_return = true
|
||||
else
|
||||
error(err)
|
||||
end
|
||||
return _return
|
||||
end
|
||||
--- Set function to run then an event is called on a thread, none of them are 'needed' but you are advised to have atleast one
|
||||
-- @usage thread:on_event('close',function) -- return true
|
||||
-- events = ['close','timeout','tick','resolve','success','error']
|
||||
-- if event is a number then it is asumed to be a game event
|
||||
-- @tparam string event the name of the event that it is called on
|
||||
-- @tparam function callback the function which is called on the event
|
||||
-- @treturn table returns self so that there can be chained
|
||||
function Server._thread:on_event(event,callback)
|
||||
local events = {'close','timeout','tick','resolve','success','error'}
|
||||
local value = table.find(events,function(v,k,find) return v == string.lower(find) end,event)
|
||||
if value and is_type(callback,'function') then
|
||||
self['_'..value] = callback
|
||||
elseif is_type(event,'number') and is_type(callback,'function') then
|
||||
if not self._events then self._events = {} end
|
||||
self._events[event] = callback
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
Event.register(defines.events.on_tick,function(event)
|
||||
if event.tick < 10 then return end
|
||||
local threads = Server._threads()
|
||||
if #threads.tick > 0 then Server.run_tick_threads() end
|
||||
if #threads.timeout > 0 then Server.check_timeouts() end
|
||||
if #threads.queue > 0 then
|
||||
local current_thread = threads.all[threads.queue[1]]
|
||||
if current_thread and current_thread:valid() then current_thread:resolve() end
|
||||
end
|
||||
end)
|
||||
|
||||
Event.register(-2,function(event)
|
||||
local threads = Server.threads()
|
||||
for uuid,thread in pairs(threads) do
|
||||
if uuid ~= '_n' then setmetatable(thread,{__index=Server._thread}) end
|
||||
end
|
||||
end)
|
||||
|
||||
Server.on_init=function(self)
|
||||
Event.register(defines.event,Server._thread_handler)
|
||||
if pcall(function() return commands._expgaming end) then
|
||||
commands.add_command('interface', 'Runs the given input from the script', {'code',true}, function(event,args)
|
||||
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, position, entity, tile = game.player, game.player.surface, game.player.force, game.player.position, game.player.selected, game.player.surface.get_tile(game.player.position);'..callback end
|
||||
if Ranking and Ranking.get_rank and game.player then callback = 'local rank = Ranking.get_rank(game.player);'..callback end
|
||||
local success, err = Server.interface(callback)
|
||||
if not success and is_type(err,'string') then local _end = string.find(err,'stack traceback') if _end then err = string.sub(err,0,_end-2) end end
|
||||
if err or err == false then player_return(err) end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
return Server
|
||||
--[[
|
||||
Thread Example:
|
||||
|
||||
local thread = Server.new_thread{name='tree-decon',data={}}
|
||||
-- user thread:on_event('tick') rather than thread:on_event(defines.events.on_tick) as it makes less lag
|
||||
thread:on_event('tick',function(self)
|
||||
local trees = self.data
|
||||
if #trees == 0 then return end
|
||||
local tree = table.remove(trees,1)
|
||||
if tree.valid then tree.destroy() end
|
||||
end)
|
||||
thread:on_event('error',function(self,err)
|
||||
-- cant see how this can cause an error
|
||||
-- but this is where error handling goes
|
||||
-- any event including on_resolve and on_tick can raise this
|
||||
end)
|
||||
thread:on_event(defines.events.on_marked_for_deconstruction,function(self,event)
|
||||
if event.entity.type == 'tree' then
|
||||
table.insert(self.data,event.entity)
|
||||
end
|
||||
end)
|
||||
thread:open()
|
||||
|
||||
local thread = Server.new_thread{name='print-place',data={}}
|
||||
thread:on_event(defines.events.on_built_entity,function(self,event)
|
||||
game.print('Events')
|
||||
end)
|
||||
thread:open()
|
||||
|
||||
all on_event functions can be chained from the thread creation rather than use varibles
|
||||
]]
|
||||
364
modules/ExpGamingCore/Sync/control.lua
Normal file
364
modules/ExpGamingCore/Sync/control.lua
Normal file
@@ -0,0 +1,364 @@
|
||||
--[[
|
||||
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-----------------------------------------------------------
|
||||
-- this file is used to allow easy syncing with out side programes
|
||||
local Sync = {}
|
||||
local Sync_gui_functions = {}
|
||||
local Sync_updates = {}
|
||||
|
||||
--- Used as a faster way to get to the ranking function, overrides previous
|
||||
-- @usage Sync.set_ranks{name=rank_name}
|
||||
function Sync.set_ranks(...)
|
||||
if Ranking then Ranking._base_preset(...) else error('Ranking module not installed') end
|
||||
end
|
||||
|
||||
--- Used to standidise the tick format for any sync info
|
||||
-- @usage Sync.tick_format(60) -- return {60,'1.00M'}
|
||||
function Sync.tick_format(tick)
|
||||
return {tick,tick_to_display_format(tick)}
|
||||
end
|
||||
|
||||
--- Prints to chat as if it were a player
|
||||
-- @usage Sync.print('Test','Cooldude2606')
|
||||
-- @param player_message the message to be printed in chat
|
||||
-- @param player_name the name of the player sending the message
|
||||
-- @param[opt] player_tag the tag apllied to the player's name
|
||||
-- @param[opt] player_colour the colour of the message
|
||||
-- @param[opt] prefix add a prefix before the chat eg [IRC]
|
||||
function Sync.print(player_message,player_name,player_tag,player_colour,prefix)
|
||||
if not player_message then return 'No Message Found' end
|
||||
local player = game.player or game.players[player_name]
|
||||
local tag = player_tag and player_tag ~= '' and ' '..player_tag or ''
|
||||
local colour = player_colour and player_colour ~= '' and player_colour or '#FFFFFF'
|
||||
local prefix = prefix and prefix..' ' or ''
|
||||
if player then
|
||||
tag = ' '..player.tag
|
||||
colour = player.chat_color
|
||||
player_name = player.name
|
||||
else
|
||||
if colour:find('#') then
|
||||
colour = Color.from_hex(colour)
|
||||
else
|
||||
colour = defines.color[player_colour]
|
||||
end
|
||||
end
|
||||
game.print(prefix..player_name..tag..': '..player_message,colour)
|
||||
end
|
||||
|
||||
--- Logs an embed to the json.data we use a js script to add things we cant here
|
||||
-- @usage Sync.emit_embeded{title='BAN',color='0x0',description='A player was banned' ... }
|
||||
-- @tparam table args a table which contains everything that the embeded will use
|
||||
-- @field title the tile of the embed
|
||||
-- @field color the color given in hex you can use Color.to_hex{r=0,g=0,b=0}
|
||||
-- @field description the description of the embed
|
||||
-- @field server_detail sting to add onto the pre-set server detail
|
||||
-- @field fieldone the filed to add to the embed (key is name) (value is text) (start value with <<inline>> to make inline)
|
||||
-- @field fieldtwo the filed to add to the embed (key is name) (value is text) (start value with <<inline>> to make inline)
|
||||
function Sync.emit_embeded(args)
|
||||
if not is_type(args,'table') then return end
|
||||
local title = is_type(args.title,'string') and args.title or ''
|
||||
local color = is_type(args.color,'string') and args.color:find("0x") and args.color or '0x0'
|
||||
local description = is_type(args.description,'string') and args.description or ''
|
||||
local server_detail = is_type(args.server_detail,'string') and args.server_detail or ''
|
||||
local mods_online = 'Mods Online: '..Sync.info().players.admins_online
|
||||
local done, fields = {title=true,color=true,description=true,server_detail=true}, {{
|
||||
name='Server Details',
|
||||
value='Server Name: {{ serverName }} Online Players: '..#game.connected_players..' '..mods_online..' Server Time: '..tick_to_display_format(game.tick)..' '..server_detail
|
||||
}}
|
||||
for key, value in pairs(args) do
|
||||
if not done[key] then
|
||||
done[key] = true
|
||||
local f = {name=key,value='',inline=false}
|
||||
local value, inline = value:gsub("<<inline>>",'',1)
|
||||
f.value = value
|
||||
if inline > 0 then f.inline = true end
|
||||
table.insert(fields,f)
|
||||
end
|
||||
end
|
||||
local log_data = {
|
||||
title=title,
|
||||
description=description,
|
||||
color=color,
|
||||
fields=fields
|
||||
}
|
||||
game.write_file('embeded.json',table.json(log_data)..'\n',true,0)
|
||||
end
|
||||
|
||||
-- set up error handle
|
||||
error.addHandler('Discord Emit',function(err)
|
||||
local color = _G.Color and Color.to_hex(defines.textcolor.bg) or '0x0'
|
||||
Sync.emit_embeded{title='SCRIPT ERROR',color=color,description='There was an error in the script @Developers ',Error=err}
|
||||
end)
|
||||
|
||||
--- used to get the number of admins currently online
|
||||
-- @usage Sync.count_admins()
|
||||
-- @treturn int the number of admins online
|
||||
function Sync.count_admins()
|
||||
if not game then return 0 end
|
||||
local _count = 0
|
||||
for _,player in pairs(game.connected_players) do
|
||||
if player.admin then _count=_count+1 end
|
||||
end
|
||||
return _count
|
||||
end
|
||||
|
||||
--- used to get the number of afk players defined by 2 min by default
|
||||
-- @usage Sync.count_afk()
|
||||
-- @tparam[opt=7200] int time in ticks that a player is called afk
|
||||
-- @treturn int the number of afk players
|
||||
function Sync.count_afk(time)
|
||||
if not game then return 0 end
|
||||
local time = time or 7200
|
||||
local _count = 0
|
||||
for _,player in pairs(game.connected_players) do
|
||||
if player.afk_time > time then _count=_count+1 end
|
||||
end
|
||||
return _count
|
||||
end
|
||||
|
||||
--- used to get the number of players in each rank and currently online
|
||||
-- @usage Sync.count_ranks()
|
||||
-- @treturn table contains the ranks and the players in that rank
|
||||
function Sync.count_ranks()
|
||||
if not game then return {'Offline'} end
|
||||
if not Ranking then return {'Ranking module not installed'} end
|
||||
local _ranks = {}
|
||||
for power,rank in pairs(Ranking._ranks()) do
|
||||
local players = rank:get_players()
|
||||
for k,player in pairs(players) do players[k] = player.name end
|
||||
local online = rank:get_players(true)
|
||||
for k,player in pairs(online) do online[k] = player.name end
|
||||
_ranks[rank.name] = {players=players,online=online,n_players=#players,n_online=#online}
|
||||
end
|
||||
return _ranks
|
||||
end
|
||||
|
||||
--- used to get the number of players either online or all
|
||||
-- @usage Sync.count_players()
|
||||
-- @tparam bolean online if true only get online players
|
||||
-- @treturn table contains player names
|
||||
function Sync.count_players(online)
|
||||
if not game then return {'Offline'} end
|
||||
local _players = {}
|
||||
local players = {}
|
||||
if online then _players = game.connected_players else _players = game.players end
|
||||
for k,player in pairs(_players) do table.insert(players,player.name) end
|
||||
return players
|
||||
end
|
||||
|
||||
--- used to get the number of players resulting in there play times
|
||||
-- @usage Sync.count_player_times()
|
||||
-- @treturn table contains players and each player is given a tick amount and a formated string
|
||||
function Sync.count_player_times()
|
||||
if not game then return {'Offline'} end
|
||||
local _players = {}
|
||||
for index,player in pairs(game.players) do
|
||||
_players[player.name] = Sync.tick_format(player.online_time)
|
||||
end
|
||||
return _players
|
||||
end
|
||||
|
||||
--- used to return the global list and set values in it
|
||||
-- @usage Sync.info{server_name='Factorio Server 2'}
|
||||
-- @tparam[opt=nil] table set keys to be replaced in the server info
|
||||
-- @return either returns success when setting or the info when not setting
|
||||
function Sync.info(set)
|
||||
if not global.exp_core then global.exp_core = {} end
|
||||
if not global.exp_core.sync then global.exp_core.sync = {
|
||||
server_name='Factorio Server',
|
||||
server_description='A factorio server for everyone',
|
||||
reset_time='On Demand',
|
||||
time='Day Mth 00 00:00:00 UTC Year',
|
||||
time_set=Sync.tick_format(0),
|
||||
last_update=Sync.tick_format(0),
|
||||
time_period=Sync.tick_format(18000),
|
||||
players={
|
||||
online=Sync.count_players(true),
|
||||
n_online=#game.connected_players,
|
||||
all=Sync.count_players(),
|
||||
n_all=#game.players,
|
||||
admins_online=Sync.count_admins(),
|
||||
afk_players=Sync.count_afk(),
|
||||
times=Sync.count_player_times()
|
||||
},
|
||||
ranks=Sync.count_ranks(),
|
||||
rockets=game.forces['player'].get_item_launched('satellite'),
|
||||
mods={'base'}
|
||||
} end
|
||||
if not set then return global.exp_core.sync
|
||||
else
|
||||
if not is_type(set,'table') then return false end
|
||||
for key,value in pairs(set) do
|
||||
global.exp_core.sync[key] = value
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--- used to return the global time and set its value
|
||||
-- @usage Sync.time('Sun Apr 1 18:44:30 UTC 2018')
|
||||
-- @tparam[opt=nil] string set the date time to be set
|
||||
-- @return either true false if setting or the date time and tick off set
|
||||
function Sync.time(set)
|
||||
local info = Sync.info()
|
||||
if not set then return info.time..' (+'..(game.tick-info.time_set[1])..' Ticks)'
|
||||
else
|
||||
if not is_type(set,'string') then return false end
|
||||
info.time = set
|
||||
info.time_set[1] = game.tick
|
||||
info.time_set[2] = tick_to_display_format(game.tick)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--- called to update values inside of the info
|
||||
-- @usage Sync.update()
|
||||
-- @return all of the new info
|
||||
function Sync.update()
|
||||
local info = Sync.info()
|
||||
info.time_period[2] = tick_to_display_format(info.time_period[1])
|
||||
info.last_update[1] = game.tick
|
||||
info.last_update[2] = tick_to_display_format(game.tick)
|
||||
info.players={
|
||||
online=Sync.count_players(true),
|
||||
n_online=#game.connected_players,
|
||||
all=Sync.count_players(),
|
||||
n_all=#game.players,
|
||||
admins_online=Sync.count_admins(),
|
||||
afk_players=Sync.count_afk(),
|
||||
times=Sync.count_player_times()
|
||||
}
|
||||
info.ranks = Sync.count_ranks()
|
||||
info.rockets = game.forces['player'].get_item_launched('satellite')
|
||||
for key,callback in pairs(Sync_updates) do info[key] = callback() end
|
||||
return info
|
||||
end
|
||||
|
||||
--- Adds a callback to be called when the info is updated
|
||||
-- @usage Sync.add_update('players',function() return #game.players end)
|
||||
-- @tparam string key the key that the value will be stored in
|
||||
-- @tparam function callback the function which will return this value
|
||||
function Sync.add_update(key,callback)
|
||||
if game then return end
|
||||
if not is_type(callback,'function') then return end
|
||||
Sync_updates[key] = callback
|
||||
end
|
||||
|
||||
--- outputs the curent server info into a file
|
||||
-- @usage Sync.emit_data()
|
||||
function Sync.emit_data()
|
||||
local info = Sync.info()
|
||||
game.write_file('server-info.json',table.json(info),false,0)
|
||||
end
|
||||
|
||||
-- will auto replace the file every 5 min by default
|
||||
Event.register(defines.events.on_tick,function(event)
|
||||
local time = Sync.info().time_period[1]
|
||||
if (event.tick%time)==0 then Sync.update() Sync.emit_data() end
|
||||
end)
|
||||
|
||||
--- Adds a emeltent to the sever info gui
|
||||
-- @usage Sync.add_to_gui('string') -- return trues
|
||||
-- @param element see examples before for what can be used, it can also be a return from Gui.inputs.add
|
||||
-- @treturn bolean based on weather it was successful or not
|
||||
function Sync.add_to_gui(element,...)
|
||||
if game then return false end
|
||||
if is_type(element,'function') then
|
||||
table.insert(Sync_gui_functions,{'function',element,...})
|
||||
elseif is_type(element,'table') then
|
||||
if element.draw then table.insert(Sync_gui_functions,{'gui',element})
|
||||
else table.insert(Sync_gui_functions,{'table',element}) end
|
||||
else table.insert(Sync_gui_functions,{'string',element}) end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
Sync.on_init=function(self)
|
||||
-- Examples for Sync.add_to_gui
|
||||
-- adds a basic string to the table
|
||||
Sync.add_to_gui('Welcome to the Explosive Gaming comunity! This is one of many servers which we host.')
|
||||
if Ranking then
|
||||
-- adds a string that can have depentant values
|
||||
Sync.add_to_gui(function(player,frame)
|
||||
return 'You have been assigned the rank \''..Ranking.get_rank(player).name..'\''
|
||||
end)
|
||||
end
|
||||
Sync.add_to_gui(function(player,frame)
|
||||
return 'This server will reset at: '..Sync.info().reset_time
|
||||
end)
|
||||
end
|
||||
-- if readme is included then see addons/guis/readme.lua for more examples
|
||||
|
||||
-- used to load the gui infomation when _G.Gui is not yet loaded
|
||||
-- internal use not recomend to be used
|
||||
function Sync._load()
|
||||
local function label_format(label,width)
|
||||
label.style.width = width
|
||||
label.style.align = 'center'
|
||||
label.style.single_line = false
|
||||
end
|
||||
Gui.center.add{
|
||||
name='server-info',
|
||||
caption='Server Info',
|
||||
tooltip='Basic info about the current server',
|
||||
draw=function(self,frame)
|
||||
frame.caption = ''
|
||||
local info = Sync.info()
|
||||
local frame = frame.add{type='flow',direction='vertical'}
|
||||
local _flow = frame.add{type='flow'}
|
||||
Gui.bar(_flow,200)
|
||||
label_format(_flow.add{
|
||||
type='label',
|
||||
caption='Welcome To '..info.server_name,
|
||||
style='caption_label'
|
||||
},180)
|
||||
Gui.bar(_flow,200)
|
||||
label_format(frame.add{
|
||||
type='label',
|
||||
caption=info.server_description,style='description_label'
|
||||
},600)
|
||||
Gui.bar(frame,600)
|
||||
local _frame = frame
|
||||
local frame = frame.add{
|
||||
type='frame',
|
||||
direction='vertical',
|
||||
style='image_frame'
|
||||
}
|
||||
frame.style.width = 600
|
||||
local text_flow = frame.add{type='flow',direction='vertical'}
|
||||
local button_flow = frame.add{type='table',column_count=3}
|
||||
for _,element in pairs(table.deepcopy(Sync_gui_functions)) do
|
||||
local _type = table.remove(element,1)
|
||||
if _type == 'function' then
|
||||
local success, err = pcall(table.remove(element,1),frame.player_index,frame,unpack(element))
|
||||
if not success then error(err) else
|
||||
if is_type(err,'table') then
|
||||
if element.draw then element:draw(button_flow).style.width = 195
|
||||
else label_format(text_flow.add{type='label',caption=err},585) end
|
||||
else label_format(text_flow.add{type='label',caption=tostring(err)},585) end
|
||||
end
|
||||
elseif _type == 'gui' then element[1]:draw(button_flow).style.width = 195
|
||||
elseif _type == 'string' then label_format(text_flow.add{type='label',caption=tostring(element[1])},585)
|
||||
elseif _type == 'table' then label_format(text_flow.add{type='label',caption=element[1]},585) end
|
||||
end
|
||||
_frame.add{
|
||||
type='label',
|
||||
caption='Press Ecs or E to close; this is only visible once!',
|
||||
style='fake_disabled_label'
|
||||
}.style.font='default-small'
|
||||
end}
|
||||
end
|
||||
|
||||
-- opens the server info gui for all new joins except admins
|
||||
Event.register(defines.events.on_player_joined_game,function(event)
|
||||
local player = Game.get_player(event)
|
||||
Gui.center.open(player,'server-info')
|
||||
end)
|
||||
|
||||
return Sync
|
||||
75
modules/ExpGamingCore/softmod.json
Normal file
75
modules/ExpGamingCore/softmod.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"name": "ExpGamingCore",
|
||||
"module": "Collection",
|
||||
"description": "Explosive Gaming Core Files",
|
||||
"keywords": ["Library","Lib","ExpGaming","Core"],
|
||||
"version": "3.4.0",
|
||||
"location": "url",
|
||||
"submodules": {
|
||||
"Commands": {
|
||||
"name": "Commands",
|
||||
"module": "commands",
|
||||
"description": "A better command handler than the base game.",
|
||||
"keywords": ["Library","Lib","ExpGaming","Core","Commands"],
|
||||
"version": "3.4.0",
|
||||
"location": "url",
|
||||
"dependencies": {
|
||||
"ExpGamingLib": ">=3.0.0",
|
||||
"ExpGamingCore/Ranking": ">=3.0.0"
|
||||
}
|
||||
},
|
||||
"Gui": {
|
||||
"name": "Gui",
|
||||
"module": "Gui",
|
||||
"description": "Adds a objective version to custom guis.",
|
||||
"keywords": ["Library","Lib","ExpGaming","Core","Gui","ExpGui"],
|
||||
"version": "3.4.0",
|
||||
"location": "url",
|
||||
"dependencies": {
|
||||
"FactorioModGui": ">=1.0.0",
|
||||
"ExpGamingLib": ">=3.0.0",
|
||||
"ExpGamingCore/Ranking": ">=3.0.0",
|
||||
"ExpGamingCore/Server": "?>=3.0.0"
|
||||
}
|
||||
},
|
||||
"Ranking": {
|
||||
"name": "Ranking",
|
||||
"module": "Ranking",
|
||||
"description": "A full ranking system for factorio.",
|
||||
"keywords": ["Library","Lib","ExpGaming","Core","Ranking","Ranks","Permissions","Roles"],
|
||||
"version": "3.4.0",
|
||||
"location": "url",
|
||||
"dependencies": {
|
||||
"ExpGamingLib": ">=3.0.0"
|
||||
}
|
||||
},
|
||||
"Server": {
|
||||
"name": "Server",
|
||||
"module": "Server",
|
||||
"description": "Adds a thread system and event listening and a admin bypass (recommend to disable /c and use optional /interface)",
|
||||
"keywords": ["Library","Lib","ExpGaming","Core","Server","Thread","Interface","Events"],
|
||||
"version": "3.4.0",
|
||||
"location": "url",
|
||||
"dependencies": {
|
||||
"ExpGamingLib": ">=3.0.0",
|
||||
"ExpGamingCore/Ranking": "?>=3.0.0",
|
||||
"ExpGamingCore/Commands": "?>=3.0.0"
|
||||
}
|
||||
},
|
||||
"Sync": {
|
||||
"name": "Sync",
|
||||
"module": "Sync",
|
||||
"description": "Allows syncing with an outside server and info panle.",
|
||||
"keywords": ["Library","Lib","ExpGaming","Core","Info","Sync","External","Discord"],
|
||||
"version": "3.4.0",
|
||||
"location": "url",
|
||||
"dependencies": {
|
||||
"ExpGamingLib": ">=3.0.0",
|
||||
"Ranking": "?>=3.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"author": "Cooldude2606",
|
||||
"contact": "Discord: Cooldude2606#5241",
|
||||
"license": "https://github.com/badgamernl/explosivegaming-main/blob/master/LICENSE"
|
||||
}
|
||||
@@ -3,12 +3,12 @@
|
||||
"module": "ExpLib",
|
||||
"description": "Adds some common functions used though out all ExpGaming modules",
|
||||
"keywords": ["ExpGaming","Lib"],
|
||||
"version": "1.0.0",
|
||||
"location": "nil",
|
||||
"main": "control",
|
||||
"version": "3.4.0",
|
||||
"location": "url",
|
||||
"dependencies": {
|
||||
"StdLib/Game": ">=1.0.0",
|
||||
"StdLib/Color": ">=1.0.0"
|
||||
"StdLib.Game": ">=0.8.0",
|
||||
"StdLib.Color": ">=0.8.0",
|
||||
"StdLib.Table": ">=0.8.0"
|
||||
},
|
||||
"author": "Cooldude2606",
|
||||
"contact": "Discord: Cooldude2606#5241",
|
||||
|
||||
6
modules/FactorioModGui/control.lua
Normal file
6
modules/FactorioModGui/control.lua
Normal file
@@ -0,0 +1,6 @@
|
||||
--- Redirect to factorio mod-gui
|
||||
-- @module Factorio Mod Gui
|
||||
-- @alias mod-gui
|
||||
-- @author Factorio Dev Team
|
||||
|
||||
return require("mod-gui")
|
||||
12
modules/FactorioModGui/softmod.json
Normal file
12
modules/FactorioModGui/softmod.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "FactorioModGui",
|
||||
"module": "mod_gui",
|
||||
"description": "A way to standadise the way mods hanndle their guis.",
|
||||
"keywords": ["Factorio","Gui","Non-Download","Included"],
|
||||
"version": "1.0.0",
|
||||
"location": "url",
|
||||
"dependencies": {},
|
||||
"author": "Factorio Dev Team",
|
||||
"contact": "Any other questions please feel free to ask on the modding help forum.",
|
||||
"license": "C:/Program Files (x86)/Steam/steamapps/common/Factorio/data/licenses.txt"
|
||||
}
|
||||
@@ -410,7 +410,7 @@ function table.val_to_str(v)
|
||||
end
|
||||
return '"'..string.gsub(v,'"', '\\"' )..'"'
|
||||
else
|
||||
return "table" == type( v) and table.to_string(v) or
|
||||
return "table" == type( v) and table.tostring(v) or
|
||||
"function" == type(v) and '"cant-display-function"' or
|
||||
"userdata" == type(v) and '"cant-display-userdata"' or
|
||||
tostring(v)
|
||||
@@ -450,7 +450,7 @@ function table.tostring(tbl)
|
||||
return "{"..table.concat(result,",") .."}"
|
||||
end
|
||||
|
||||
--- Simmilar to table.to_string but converts a lua table to a json one
|
||||
--- Simmilar to table.tostring but converts a lua table to a json one
|
||||
-- @usage local a = {k1='foo',k2='bar'}
|
||||
-- talbe.json(a) -- return '{"k1":"foo","k2":"bar"}'
|
||||
-- @tparam table lua_table the table to convert
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "FactorioStdLib",
|
||||
"module": "StdLib",
|
||||
"module": "Collection",
|
||||
"description": "Factorio Standard Library Projects",
|
||||
"keywords": ["Standard Library","Lib","StdLib"],
|
||||
"version": "0.8.0",
|
||||
"location": "nil",
|
||||
"location": "url",
|
||||
"submodules": {
|
||||
"Color": {
|
||||
"name": "Color",
|
||||
@@ -12,7 +12,7 @@
|
||||
"description": "A defines module for retrieving colors by name.",
|
||||
"keywords": ["Standard Library","Lib","StdLib","Color","Extends"],
|
||||
"version": "0.8.0",
|
||||
"location": "color",
|
||||
"location": "url",
|
||||
"dependencies": {}
|
||||
},
|
||||
"Game": {
|
||||
@@ -21,7 +21,7 @@
|
||||
"description": "The game module.",
|
||||
"keywords": ["Standard Library","Lib","StdLib","Game","Extends"],
|
||||
"version": "0.8.0",
|
||||
"location": "game",
|
||||
"location": "url",
|
||||
"dependencies": {}
|
||||
},
|
||||
"String": {
|
||||
@@ -30,7 +30,7 @@
|
||||
"description": "Extends Lua 5.2 string.",
|
||||
"keywords": ["Standard Library","Lib","StdLib","String","Extends"],
|
||||
"version": "0.8.0",
|
||||
"location": "string",
|
||||
"location": "url",
|
||||
"dependencies": {}
|
||||
},
|
||||
"Table": {
|
||||
@@ -39,7 +39,7 @@
|
||||
"description": "Extends Lua 5.2 table.",
|
||||
"keywords": ["Standard Library","Lib","StdLib","Table","Extends"],
|
||||
"version": "0.8.0",
|
||||
"location": "table",
|
||||
"location": "url",
|
||||
"dependencies": {}
|
||||
},
|
||||
"Time": {
|
||||
@@ -48,7 +48,7 @@
|
||||
"description": "A defines module for retrieving the number of ticks in 1 unit of time.",
|
||||
"keywords": ["Standard Library","Lib","StdLib","Time","Extends"],
|
||||
"version": "0.8.0",
|
||||
"location": "time",
|
||||
"location": "url",
|
||||
"dependencies": {}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
--- Used to index the files to be loaded
|
||||
-- @script index.lua
|
||||
return {
|
||||
['ExpLib']='/modules/ExpGamingLib/control',
|
||||
['Game']='/modules/FactorioStdLib/game',
|
||||
['Time']='/modules/FactorioStdLib/time',
|
||||
['Color']='/modules/FactorioStdLib/color',
|
||||
['table']='/modules/FactorioStdLib/table',
|
||||
['string']='/modules/FactorioStdLib/string',
|
||||
['mod_gui']='/modules/FactorioModGui',
|
||||
['ExpLib']='/modules/ExpGamingLib',
|
||||
['Game']='/modules/FactorioStdLib/Game',
|
||||
['Time']='/modules/FactorioStdLib/Time',
|
||||
['Color']='/modules/FactorioStdLib/Color',
|
||||
['table']='/modules/FactorioStdLib/Table',
|
||||
['string']='/modules/FactorioStdLib/String',
|
||||
['Ranking']='/modules/ExpGamingCore/Ranking',
|
||||
['commands']='/modules/ExpGamingCore/Commands',
|
||||
['Gui']='/modules/ExpGamingCore/Gui',
|
||||
['Server']='/modules/ExpGamingCore/Server',
|
||||
['Sync']='/modules/ExpGamingCore/Sync',
|
||||
}
|
||||
Reference in New Issue
Block a user