Added Module: ExpGamingCore

This commit is contained in:
Cooldude2606
2018-05-30 13:50:38 +01:00
parent eeb44c0c93
commit 24598e594a
33 changed files with 250 additions and 189 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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