[READ-ONLY] Mirror of https://github.com/thoda-dev/DU-Industry-HUD. A simple HUD for monitoring and managing industry in Dual Universe
dual-universe lua
0

Configure Feed

Select the types of activity you want to include in your feed.

fix source

Thomas (Feb 21, 2023, 7:29 PM +0100) 2f760937 5a5124c0

+1064
+4
Master Program/source/slot1/onContentUpdate.lua
··· 1 + local content = schematicContainer.getContent() 2 + for _,s in pairs(content) do 3 + schematicStorage["s" .. s.id] = s.quantity 4 + end
+6
Master Program/source/system/onActionStart.lua
··· 1 + if hud.actions.start[action] ~= nil then 2 + local success, message = pcall(hud.actions.start[action]) 3 + if not success then 4 + system.print("Action Start '" .. action .. "' Error : " .. message) 5 + end 6 + end
+6
Master Program/source/system/onActionStop.lua
··· 1 + if hud.actions.stop[action] ~= nil then 2 + local success, message = pcall(hud.actions.stop[action]) 3 + if not success then 4 + system.print("Action Stop '" .. action .. "' Error : " .. message) 5 + end 6 + end
+13
Master Program/source/system/onInputText.lua
··· 1 + if tonumber(text) then 2 + if #text > 8 then 3 + system.print("the value should not be higher than 99 999 999.") 4 + else 5 + craft_quantity_digits = {"0","0","0","0","0","0","0","0"} 6 + for i = #text, 1, -1 do 7 + local c = text:sub(i,i) 8 + craft_quantity_digits[9-(#text-(i-1))] = c 9 + end 10 + end 11 + else 12 + system.print("You must type a Number") 13 + end
+12
Master Program/source/system/onUpdate.lua
··· 1 + --[[ 2 + DU-Nested-Coroutines by Jericho 3 + Permit to easier avoid CPU Load Errors 4 + Source available here: https://github.com/Jericho1060/du-nested-coroutines 5 + ]]-- 6 + 7 + if coroutine.status(MainCoroutine) == "dead" then 8 + MainCoroutine = coroutine.create(runCoroutines) 9 + end 10 + if coroutine.status(MainCoroutine) == "suspended" then 11 + assert(coroutine.resume(MainCoroutine)) 12 + end
+1022
Master Program/source/unit/onStart.lua
··· 1 + version = "v4.2.1" 2 + --[[ 3 + DU Industry HUD By Jericho 4 + ]] 5 + local log_split = "=================================================" 6 + --printing version in lua chat 7 + system.print(log_split)local a=""local b=math.ceil((50-#version-2)/2)for c=1,b,1 do a=a..'='end;a=a.." "..version.." "for c=1,b,1 do a=a..'='end;system.print(a)system.print(log_split) 8 + --[[ 9 + Lua parameters 10 + ]] 11 + fontSize = 12 --export: the fonct size 12 + showRecipeData = true --export: display the recipe ingredients in the machine detail 13 + 14 + enableRefinerMonitoring = true --export: enable or disable the Refiners monitoring 15 + enableAssemblyMonitoring = true --export: enable or disable the Assembly lines monitoring 16 + enableSmelterMonitoring = true --export: enable or disable the Smelters monitoring 17 + enableChemicalMonitoring = true --export: enable or disable the Chemical industries monitoring 18 + enableElectronicsMonitoring = true --export: enable or disable the Electronics Industries monitoring 19 + enableGlassMonitoring = true --export: enable or disable the Glass Furnace monitoring 20 + enableHoneycombMonitoring = true --export: enable or disable the Honeycomb Refineries monitoring 21 + enableRecyclerMonitoring = true --export: enable or disable the Recyclers monitoring 22 + enableMetalworkMonitoring = true --export: enable or disable the Metalworks monitoring 23 + enable3DPrinterMonitoring = true --export: enable or disable the 3D Printers monitoring 24 + enableTransferMonitoring = true --export: enable or disable the transfer units monitoring 25 + enableRemoteControl = true --export: enable the HUD to control machines (start/stop/batch/maintain) 26 + elementsByPage = 20 --export: maximum amount of elements displayed on a single page 27 + dateFormat = "en" --export: the country code to format the date 28 + maxAmountOfElementsLoadedByFrame = 500 --export: if cpu load errors at start, lower that value 29 + machinesRefreshedByFrame = 100 --how many machines are refreshed by frame 30 + machineDetailDisplayDistance = 0 --export: the distance in meters to display the machine details 31 + displayType = 0 --export: the default display type: 0=ALL, 1=Table, 2=Augmented Reality 32 + displayMode = 0 --export: the default display type: 0=ALL, 1=Industry Only, 2=Storage Only, 3=None 33 + sortingType = 1 --export: the default sorting of elements in table: 1=Element Name, 2=Item in containers or product of industries, 3=Element ID 34 + 35 + 36 + --[[ 37 + receivers channels for each type of machine 38 + ]] 39 + channel_for_refiner = "receiver_refiner" --export: receiver channel to send orders to refiners 40 + channel_for_assembly = "receiver_assembly" --export: receiver channel to send orders to assembly lines 41 + channel_for_smelter = "receiver_smelters" --export: receiver channel to send orders to smelters 42 + channel_for_chemical = "receiver_chemical" --export: receiver channel to send orders to chemical indutries 43 + channel_for_electronics = "receiver_electronics" --export: receiver channel to send orders to electronic industries 44 + channel_for_glass = "receiver_glass" --export: receiver channel to send orders to glass furnace 45 + channel_for_honeycomb = "receiver_honeycomb_recycler" --export: receiver channel to send orders to honeycomb refiniries 46 + channel_for_recycler = "receiver_honeycomb_recycler" --export: receiver channel to send orders to recylers 47 + channel_for_metalwork = "receiver_metalworks" --export: receiver channel to send orders to metalworks 48 + channel_for_3d_printer = "receiver_3dprinters" --export: receiver channel to send orders to 3d printers 49 + channel_for_transfer = "receiver_transfert" --export: receiver channel to send orders to tranfer units 50 + 51 + --Storage options 52 + containerProficiencyLvl = 5 --export: Talent level for Container Proficiency 53 + containerOptimizationLvl = 0 --export: Talent level for Container Optimization 54 + storages_prefix_list = 's1,s2,s3,s4,s5,s6,s7,s8,s9' --export: the list of the prefixes used for the storage monitoring, comma separated values 55 + 56 + --split a string on a delimiter By jericho 57 + function strSplit(a,b)result={}for c in(a..b):gmatch("(.-)"..b)do table.insert(result,c)end;return result end 58 + --formatting numbers by adding a space between thousands by Jericho 59 + function format_number(a)local b=a;while true do b,k=string.gsub(b,"^(-?%d+)(%d%d%d)",'%1 %2')if k==0 then break end end;return b end 60 + --Utility functions By jericho, see full source at https://github.com/Jericho1060/DualUniverse 61 + function removeDuplicatesInTable(a)local b={}local c={}for d,e in ipairs(a)do if not b[e]then c[#c+1]=e;b[e]=true end end;return c end;function strSplit(a,b)result={}for c in(a..b):gmatch("(.-)"..b)do table.insert(result,c)end;return result end;function SecondsToClockString(a)local a=tonumber(a)if a==nil or a<=0 then return"-"else days=string.format("%2.f",math.floor(a/(3600*24)))hours=string.format("%2.f",math.floor(a/3600-days*24))mins=string.format("%2.f",math.floor(a/60-hours*60-days*24*60))secs=string.format("%2.f",math.floor(a-hours*3600-days*24*60*60-mins*60))str=""if tonumber(days)>0 then str=str..days.."d "end;if tonumber(hours)>0 then str=str..hours.."h "end;if tonumber(mins)>0 then str=str..mins.."m "end;if tonumber(secs)>0 then str=str..secs.."s"end;return str end end;function removeQualityInName(a)if not a then return''end;return a:lower():gsub('basic ',''):gsub('uncommon ',''):gsub('advanced ',''):gsub('rare ',''):gsub('exotic ','')end;function has_value(a,b)for c,d in ipairs(a)do if d==b then return true end end;return false end 62 + --return RGB colors calculated from a gradient between two colors 63 + function getRGBGradient(a,b,c,d,e,f,g,h,i,j)a=-1*math.cos(a*math.pi)/2+0.5;local k=0;local l=0;local m=0;if a>=.5 then a=(a-0.5)*2;k=e-a*(e-h)l=f-a*(f-i)m=g-a*(g-j)else a=a*2;k=b-a*(b-e)l=c-a*(c-f)m=d-a*(d-g)end;return k,l,m end 64 + --time script to get client date and time by Jericho, see full source at https://github.com/Jericho1060/DualUniverse 65 + function DUCurrentDateTime(a)local b=system.getUtcTime()if not a then b=b+system.getUtcOffset()end;local c=24*60*60;local d=365*c;local e=d+c;local f=4*d+c;local g=4;local h=1970;local i={-1,30,58,89,119,150,180,211,242,272,303,333,364}local j={}for k=1,2 do j[k]=i[k]end;for k=3,13 do j[k]=i[k]+1 end;local l,m,n,o,p,q,r,s;local t=i;s=b;l=math.floor(s/f)s=s-l*f;l=l*4+h;if s>=d then l=l+1;s=s-d;if s>=d then l=l+1;s=s-d;if s>=e then l=l+1;s=s-e else t=j end end end;m=math.floor(s/c)s=s-m*c;local n=1;while t[n]<m do n=n+1 end;n=n-1;local o=m-t[n]p=(math.floor(b/c)+g)%7;if p==0 then p=7 end;q=math.floor(s/3600)s=s-q*3600;r=math.floor(s/60)function round(u,v)if v then return utils.round(u/v)*v end;return u>=0 and math.floor(u+0.5)or math.ceil(u-0.5)end;s=round(s-r*60)local w={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}local x={"Mon","Tue","Wed","Thu","Fri","Sat","Sun"}local y={"January","February","March","April","May","June","July","August","September","October","November","December"}local z={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}return l,n,o,q,r,s,p,w[p],x[p],y[n],z[n],m+1 end 66 + 67 + --databank hub library By Jericho, see full source at https://github.com/Jericho1060/DualUniverse 68 + bankhub={}function bankhub:new(banks)o={}setmetatable(o,self)self.__index=self;o.banks=banks or{}function o.clear()return o:_clear()end;function o.getNbKeys()return o:_getNbKeys()end;function o.getKeys()return o:_getKeys()end;function o.hasKey(a)return o:_hasKey(a)end;function o.getStringValue(a)return o:_getStringValue(a)end;function o.getIntValue(a)return o:_getIntValue(a)end;function o.getFloatValue(a)return o:_getFloatValue(a)end;return o end;function bankhub:add(b)table.insert(self.banks,b)self.banks_size=#self.banks end;function bankhub:_clear()for c,d in pairs(self.banks)do d.clear()end end;function bankhub:_getNbKeys()local e=0;for c,d in pairs(self.banks)do e=e+d.getNbKeys()end;return e end;function bankhub:_getKeys()local e={}for c,d in pairs(self.banks)do local f=json.decode(d.getKeys())for c,g in pairs(f)do table.insert(e,g)end end;return json.encode(e)end;function bankhub:_hasKey(a)for c,d in pairs(self.banks)do if d.hasKey(a)==1 then return 1 end end;return 0 end;function bankhub:_getStringValue(a)for c,d in pairs(self.banks)do if d.hasKey(a)==1 then return d.getStringValue(a)end end;return nil end;function bankhub:_getIntValue(a)for c,d in pairs(self.banks)do if d.hasKey(a)==1 then return banks.getIntValue(a)end end;return nil end;function bankhub:_getFloatValue(a)for c,d in pairs(self.banks)do if d.hasKey(a)==1 then return banks.getFloatValue(a)end end;return nil end 69 + --time script to get client date and time by Jericho, see full source at https://github.com/Jericho1060/DualUniverse 70 + function DUCurrentDateTime(a)local b=system.getUtcTime()if not a then b=b+system.getUtcOffset()end;local c=24*60*60;local d=365*c;local e=d+c;local f=4*d+c;local g=4;local h=1970;local i={-1,30,58,89,119,150,180,211,242,272,303,333,364}local j={}for k=1,2 do j[k]=i[k]end;for k=3,13 do j[k]=i[k]+1 end;local l,m,n,o,p,q,r,s;local t=i;s=b;l=math.floor(s/f)s=s-l*f;l=l*4+h;if s>=d then l=l+1;s=s-d;if s>=d then l=l+1;s=s-d;if s>=e then l=l+1;s=s-e else t=j end end end;m=math.floor(s/c)s=s-m*c;local n=1;while t[n]<m do n=n+1 end;n=n-1;local o=m-t[n]p=(math.floor(b/c)+g)%7;if p==0 then p=7 end;q=math.floor(s/3600)s=s-q*3600;r=math.floor(s/60)function round(u,v)if v then return utils.round(u/v)*v end;return u>=0 and math.floor(u+0.5)or math.ceil(u-0.5)end;s=round(s-r*60)local w={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}local x={"Mon","Tue","Wed","Thu","Fri","Sat","Sun"}local y={"January","February","March","April","May","June","July","August","September","October","November","December"}local z={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}return l,n,o,q,r,s,p,w[p],x[p],y[n],z[n],m+1 end 71 + 72 + statusList = {"STOPPED","RUNNING","MISSING INGREDIENT","OUTPUT FULL","NO OUTPUT CONTAINER","PENDING","MISSING SCHEMATIC","SERVER ERROR", "STOP REQUESTED"} 73 + function getIndustryStatusClass(status) 74 + if status == 1 then 75 + return "text-info" 76 + elseif status == 2 then 77 + return "text-success" 78 + elseif ((status >= 3) and (status <= 5)) or (status == 7) then 79 + return "text-danger" 80 + elseif status == 6 then 81 + return "text-primary" 82 + elseif status >= 8 and status <= 9 then 83 + return "text-warning" 84 + end 85 + return "" --default value for other status that can be added 86 + end 87 + function getIndustryStatusBgClass(status) 88 + if status then 89 + if status == 1 then 90 + return "bg-info" 91 + elseif status == 2 then 92 + return "bg-success" 93 + elseif ((status >= 3) and (status <= 5)) or (status == 7) then 94 + return "bg-danger" 95 + elseif status == 6 then 96 + return "bg-primary" 97 + elseif status >= 8 and status <= 9 then 98 + return "bg-warning" 99 + end 100 + end 101 + return "" --default value for other status that can be added 102 + end 103 + function getIndustryStatusBorderClass(status) 104 + if status then 105 + if status == 1 then 106 + return "border-info" 107 + elseif status == 2 then 108 + return "border-success" 109 + elseif ((status >= 3) and (status <= 5)) or (status == 7) then 110 + return "border-danger" 111 + elseif status == 6 then 112 + return "border-primary" 113 + elseif status >= 8 and status <= 9 then 114 + return "border-warning" 115 + end 116 + end 117 + return "" --default value for other status that can be added 118 + end 119 + function ConvertLocalToWorld(a,b,c,d,e)local f={a[1]*c[1],a[1]*c[2],a[1]*c[3]}local g={a[2]*d[1],a[2]*d[2],a[2]*d[3]}local h={a[3]*e[1],a[3]*e[2],a[3]*e[3]}return{f[1]+g[1]+h[1]+b[1],f[2]+g[2]+h[2]+b[2],f[3]+g[3]+h[3]+b[3]}end 120 + 121 + 122 + channels = {} 123 + channels['refiner'] = channel_for_refiner 124 + channels['assembly line'] = channel_for_assembly 125 + channels['smelter'] = channel_for_smelter 126 + channels['chemical industry'] = channel_for_chemical 127 + channels['electronics industry'] = channel_for_electronics 128 + channels['glass furnace'] = channel_for_glass 129 + channels['honeycomb refinery'] = channel_for_honeycomb 130 + channels['recycler'] = channel_for_recycler 131 + channels['metalwork industry'] = channel_for_metalwork 132 + channels['3d printer'] = channel_for_3d_printer 133 + channels['transfer unit'] = channel_for_transfer 134 + 135 + bootstrap_css_colors = [[<style>.text-white {color: #fff !important;}.text-primary {color: #007bff !important;}.text-secondary {color: #6c757d !important;}.text-success {color: #28a745 !important;}.text-info {color: #17a2b8 !important;}.text-warning {color: #ffc107 !important;}.text-danger {color: #dc3545 !important;}.text-light {color: #f8f9fa !important;}.text-dark {color: #343a40 !important;}.text-body {color: #212529 !important;}.text-muted {color: #6c757d !important;}.text-black-50 {color: rgba(0, 0, 0, 0.5) !important;}.text-white-50 {color: rgba(255, 255, 255, 0.5) !important;}.bg-primary {background-color: #007bff !important;}.bg-secondary {background-color: #6c757d !important;}.bg-success {background-color: #28a745 !important;}.bg-info {background-color: #17a2b8 !important;}.bg-warning {background-color: #ffc107 !important;}.bg-danger {background-color: #dc3545 !important;}.bg-light {background-color: #f8f9fa !important;}.bg-dark {background-color: #343a40 !important;}.bg-white {background-color: #fff !important;}.bg-transparent {background-color: transparent !important;}.border-primary {border-color: #007bff !important;}.border-secondary {border-color: #6c757d !important;}.border-success {border-color: #28a745 !important;}.border-info {border-color: #17a2b8 !important;}.border-warning {border-color: #ffc107 !important;}.border-danger {border-color: #dc3545 !important;}.border-light {border-color: #f8f9fa !important;}.border-dark {border-color: #343a40 !important;}.border-white {border-color: #fff !important;} 136 + </style>]] 137 + base_css = [[<style>.ib{position:absolute;opacity:.75;transform: translate(-50%, -50%);}.tier0{font-weight:bold;padding:5px;margin-right:5px;color:black;background-color:#fff;}.tier1{font-weight:bold;padding:5px;margin-right:5px;color:black;background-color:#fff;}.tier2{font-weight:bold;padding:5px;margin-right:5px;color:white;background-color:green;}.tier3{font-weight:bold;padding:5px;margin-right:5px;color:white;background-color:blue;}.tier4{font-weight:bold;padding:5px;margin-right:5px;color:white;background-color:purple;}.tier5{font-weight:bold;padding:5px;margin-right:5px;color:white;background-color:orange;}hr{border-top:1px solid #343a40;border-collapse:collapse;}.hr-light{border-top:1px solid #f8f9fa;}.hud_container{z-index:1000;font-size:]] .. fontSize .. [[px;border: 1px solid black;border-radius:5px;background-color: rgba(15,24,29,.85);padding:10px;}.hud_time{position: absolute;bottom: ]] .. tostring((100/1080)*100) .. [[vh;right: ]] .. tostring((10/1920)*100) .. [[vw;text-transform: uppercase;font-weight: bold;}.hud_machine_types_container{position: absolute;top: ]] .. tostring((80/1080)*100) .. [[vh;left: ]] .. tostring((10/1920)*100) .. [[vw;text-transform: uppercase;font-weight: bold;}.hud_machine_status_container{position: absolute;top: ]] .. tostring((10/1080)*100) .. [[vh;left: ]] .. tostring((10/1920)*100) .. [[vw;text-transform: uppercase;font-weight: bold;}.hud_table_container{position: absolute;top:]] .. tostring((80/1080)*100) .. [[vh;left:]] .. tostring((225/1920)*100) .. [[vw;}.hud_table_container td,.hud_table_container th, .hud_machine_control th{border-bottom:1px solid #f8f9fa;}small{font-size:.75em;}.hud_table_container td.row_selected,.hud_table_container th.row_selected{border:2px solid green;}.hud_machine_control{position: absolute;top: ]] .. tostring((300/1080)*100) .. [[vh;right: ]] .. tostring((10/1920)*100) .. [[vw;text-transform: uppercase;font-weight: bold;}</style>]] 138 + 139 + 140 + databanks = {} 141 + core = nil 142 + emitter = nil 143 + industries_id = {} 144 + storages_id = {} 145 + industries = {} 146 + storages = {} 147 + elementsTypes = {} 148 + storagesTypes = {} 149 + schematicContainer = nil 150 + schematicContainerId = construct.getSchematicContainerId() 151 + schematicStorage = {} 152 + for slot_name, slot in pairs(unit) do 153 + if 154 + type(slot) == "table" 155 + and type(slot.export) == "table" 156 + and slot.getClass 157 + then 158 + if slot.getClass():lower() == 'databankunit' then 159 + table.insert(databanks, slot) 160 + elseif slot.getClass():lower():find("coreunit") then 161 + core = slot 162 + elseif slot.getClass():lower() == 'emitterunit' then 163 + emitter = slot 164 + elseif schematicContainerId ~= nil and slot.getClass():lower():find('container') then 165 + if slot.getId() == schematicContainerId then 166 + schematicContainer = slot 167 + end 168 + end 169 + end 170 + end 171 + 172 + if core == nil then 173 + system.print("Connection to the core is missing") 174 + unit.exit() 175 + end 176 + if schematicContainerId == nil then 177 + system.print("No Schematic Container set on the Construct") 178 + end 179 + if schematicContainer == nil then 180 + system.print("Schematic Container is not linked to the board") 181 + end 182 + 183 + if emitter == nil then 184 + enableRemoteControl = false 185 + system.print("Connect an Emitter to enable machine control from industry") 186 + end 187 + if #databanks == 0 then 188 + enableRemoteControl = false 189 + system.print("No Databank linked") 190 + end 191 + 192 + --init of bank hub 193 + Storage = bankhub:new(databanks) 194 + 195 + --construct pos for AR data 196 + constructPos = construct.getWorldPosition() 197 + constructRight = construct.getWorldRight() 198 + constructForward = construct.getWorldForward() 199 + constructUp = construct.getWorldUp() 200 + 201 + --script variables 202 + storage_prefix = strSplit(storages_prefix_list, ',') 203 + displayTypes = {"ALL", "Table", "Augmented Reality"} 204 + displayModes = {"ALL", "Industry", "Storage", "None"} 205 + sortingTypes = {"Element Name", "Item", "Element ID"} 206 + init = false 207 + initIndex = 1 208 + elementsIdList = {} 209 + machines_count = {} 210 + storages_count = {} 211 + machines_positions = {} 212 + storages_positions = {} 213 + system.showScreen(true) 214 + statusFilter = 0 215 + statusFilterType = 0 216 + maxFilterType = 0 217 + maxOnPage=1 218 + html_filters = "" 219 + html_filters_types = "" 220 + html_filter_storage = "" 221 + html_machines = "" 222 + html_storage = "" 223 + html_time = "" 224 + html_ar_selected = "" 225 + html_control = "" 226 + html_credits = [[<div class="hud_container" style="position:absolute;left:5px;bottom:5px;font-size:10px;padding:5px;">]] .. version .. [[ - Powered By jericho1060</div>]] 227 + 228 + --pagination var 229 + page = 1 230 + maxPage = 1 231 + selectedRow = 1 232 + selected_machine=nil 233 + selected_container=nil 234 + 235 + --control machine var 236 + command_1 = "" 237 + command_2 = "" 238 + command_3 = "" 239 + craft_quantity_digits = {"0","0","0","0","0","0","0","0"} 240 + 241 + --keyPressed 242 + ctrlPressed = false 243 + 244 + 245 + --[[ 246 + DU INDUSTRY HUD By Jericho 247 + ]] 248 + schematicRefreshTime = 0 249 + hud = {} 250 + hud.coroutines = {} 251 + if schematicContainer ~= nil then 252 + hud.coroutines.getSchematics = function () 253 + schematicRefreshTime = math.ceil(schematicContainer.updateContent()) 254 + end 255 + end 256 + hud.coroutines.init = function() 257 + if not init then 258 + elementsTypes = {} 259 + industries_id = {} 260 + industries = {} 261 + 262 + storagesTypes = {} 263 + storages_id = {} 264 + storages = {} 265 + 266 + elementsIdList = core.getElementIdList() 267 + 268 + for index,id in ipairs(elementsIdList) do 269 + elementType = core.getElementDisplayNameById(id):lower() 270 + if (elementType:find("assembly line") and enableAssemblyMonitoring == true) or 271 + (elementType:find("glass furnace") and enableGlassMonitoring == true) or 272 + (elementType:find("3d printer") and enable3DPrinterMonitoring == true) or 273 + (elementType:find("smelter") and enableSmelterMonitoring == true) or 274 + (elementType:find("recycler") and enableRecyclerMonitoring == true) or 275 + (elementType:find("refinery") and enableHoneycombMonitoring == true) or 276 + (elementType:find("refiner") and enableRefinerMonitoring == true) or 277 + (elementType:find("industry") 278 + and ( 279 + (elementType:find("chemical") and enableChemicalMonitoring == true) or 280 + (elementType:find("electronics") and enableElectronicsMonitoring == true) or 281 + (elementType:find("metalwork") and enableMetalworkMonitoring == true) 282 + ) 283 + ) or 284 + (elementType == "transfer unit" and enableTransferMonitoring == true) or 285 + elementType:lower():find("container") 286 + then 287 + local formatedType = removeQualityInName(elementType) 288 + local pos = core.getElementPositionById(id) 289 + if elementType:lower():find("container") then 290 + if storages_count[formatedType] ~= nil then 291 + storages_count[formatedType] = storages_count[formatedType] + 1 292 + else 293 + storages_count[formatedType] = 1 294 + end 295 + table.insert(storages_id, id) 296 + storages_positions['i'..id] = pos 297 + table.insert(storagesTypes, formatedType) 298 + else 299 + pos[3] = pos[3] + 1 300 + if machines_count[formatedType] ~= nil then 301 + machines_count[formatedType] = machines_count[formatedType] + 1 302 + else 303 + machines_count[formatedType] = 1 304 + end 305 + table.insert(industries_id, id) 306 + machines_positions['i'..id] = pos 307 + table.insert(elementsTypes, formatedType) 308 + end 309 + end 310 + 311 + if index % maxAmountOfElementsLoadedByFrame == 0 then 312 + coroutine.yield(self.init) 313 + end 314 + end 315 + elementsTypes = removeDuplicatesInTable(elementsTypes) 316 + table.sort(elementsTypes, function(a,b) return a:lower() < b:lower() end) 317 + selected_type = elementsTypes[1] 318 + init = true 319 + system.print("All elements loaded") 320 + system.print(#storages_id .. " storage elements found") 321 + system.print(#industries_id .. " industries found") 322 + end 323 + end 324 + hud.coroutines.loadIndustries = function() 325 + if init and (displayMode == 0 or displayMode == 1) then 326 + for index,id in ipairs(industries_id) do 327 + local pos = machines_positions['i'..id] 328 + local data = core.getElementIndustryInfoById(id) 329 + if industries["i"..tostring(id)] == nil then industries["i"..tostring(id)] = {} end 330 + local mode = "" 331 + local tableMode = "" 332 + local maintainOrBatchQuantity = 0 333 + if data.maintainProductAmount > 0 then 334 + mode = "<div><strong>Mode:</strong> Maintain " .. math.floor(data.currentProductAmount) .."/" .. math.floor(data.maintainProductAmount) .. "</div>" 335 + tableMode = "Maintain " .. math.floor(data.currentProductAmount) .."/" .. math.floor(data.maintainProductAmount) 336 + maintainOrBatchQuantity=math.floor(data.maintainProductAmount) 337 + elseif data.batchesRequested > 0 and data.batchesRequested <= 99999999 then 338 + local current = data.batchesRequested - data.batchesRemaining 339 + if data.batchesRemaining < 0 then current = 0 end 340 + mode = "<div><strong>Mode:</strong> Produce " .. math.floor(current) .. "/" .. math.floor(data.batchesRequested) .. "</div>" 341 + tableMode = "Produce " .. math.floor(current) .. "/" .. math.floor(data.batchesRequested) 342 + maintainOrBatchQuantity=math.floor(data.batchesRequested) 343 + end 344 + local production = {locDisplayNameWithSize="No recipe selected", tier=0} 345 + local schematicName = "" 346 + local tableSchematicName = "" 347 + local tableSchematicQuantity = "" 348 + local schematicColor = "success" 349 + local state = data.state 350 + local time="" 351 + local tableTime="" 352 + local recipe="" 353 + local industryType = core.getElementDisplayNameById(id) 354 + local schematicId = data.requiredSchematicIds[1] or 0 355 + if schematicId > 0 and not industryType:lower():find("transfer") then 356 + local sch = system.getItem(schematicId) 357 + local shematicQuantity = schematicStorage["s" .. schematicId] or 0 358 + if shematicQuantity < data.requiredSchematicAmount then schematicColor = "danger" end 359 + schematicName = '<div><strong>Schematic:</strong> ' .. format_number(shematicQuantity):gsub(".0", "") .. "/" .. format_number(data.requiredSchematicAmount) .. " " .. sch.locDisplayNameWithSize .. "</div>" 360 + tableSchematicName = sch.locDisplayNameWithSize 361 + tableSchematicQuantity = format_number(shematicQuantity):gsub(".0", "") .. "/" .. format_number(data.requiredSchematicAmount) 362 + end 363 + if #data.currentProducts > 0 then 364 + local item_id = data.currentProducts[1].id 365 + production = system.getItem(item_id) 366 + if id ~= "947806142" and id ~= "1010524904" and not industryType:lower():find("transfer") then 367 + if showRecipeData then 368 + local rdata = system.getRecipes(item_id) 369 + if #rdata > 0 then 370 + local r = nil 371 + for _,recipe in pairs(rdata) do 372 + if recipe.products[1].id == item_id then 373 + r = recipe 374 + break 375 + end 376 + end 377 + if r then 378 + recipe = "<div><strong>Recipe:</strong>" 379 + for _,v in pairs(r.ingredients) do 380 + local item = system.getItem(v.id) 381 + recipe = recipe .. "<br>&nbsp;&nbsp;&nbsp;&nbsp;- " .. v.quantity .. " x " .. item.locDisplayNameWithSize 382 + end 383 + recipe = recipe .. "</div>" 384 + end 385 + end 386 + end 387 + end 388 + if data.remainingTime == 0 and data.state == 2 then 389 + state = 8 390 + end 391 + if data.stopRequested and data.state ~= 1 then 392 + state = 9 393 + end 394 + if data.remainingTime > 0 then 395 + time = "<div><strong>Time:</strong> " .. SecondsToClockString(data.remainingTime) .. "</div>" 396 + tableTime = SecondsToClockString(data.remainingTime) 397 + end 398 + end 399 + local productionName = '<div><strong>Product</strong>: ' .. production.locDisplayNameWithSize .. '</div>' 400 + local productId = '' 401 + if production.id then 402 + productId = "<div><strong>Main Product ID:</strong> " .. production.id .. "</div>" 403 + end 404 + local elementName = core.getElementNameById(id) 405 + industries["i"..tostring(id)] = { 406 + id=id, 407 + screenPos=library.getPointOnScreen(ConvertLocalToWorld(pos, constructPos, constructRight, constructForward, constructUp)), 408 + name="<div><strong>Industry Name:</strong> [" .. id .. "] " .. elementName .. "</div>", 409 + tableName=elementName, 410 + type="<div><strong>Industry Type:</strong> " .. industryType .. "</div>", 411 + tableType=industryType, 412 + typeFilter=removeQualityInName(industryType), 413 + state=state, 414 + production=production, 415 + productId=productId, 416 + productionName=productionName, 417 + mode=mode, 418 + tableMode=tableMode, 419 + remainingTime=time, 420 + tableTime=tableTime, 421 + schematic=schematicName, 422 + schematicColor=schematicColor, 423 + maintainOrBatchQuantity=maintainOrBatchQuantity, 424 + tableSchematic=tableSchematicName, 425 + tableSchematicQuantity=tableSchematicQuantity, 426 + recipe=recipe, 427 + stopRequested=data.stopRequested 428 + } 429 + if index % machinesRefreshedByFrame == 0 then 430 + coroutine.yield(self.loadIndustries) 431 + end 432 + end 433 + end 434 + end 435 + hud.coroutines.loadStorage = function() 436 + for index,id in ipairs(storages_id) do 437 + local pos = storages_positions['i'..id] 438 + local elementType = core.getElementDisplayNameById(id) 439 + local base_name = core.getElementNameById(id) 440 + local splitted = strSplit(base_name,'_') 441 + local item_id = nil 442 + local prefix = nil 443 + if #splitted > 1 then 444 + prefix = splitted[1] 445 + item_id = splitted[2] 446 + end 447 + local container = { 448 + id = id, 449 + type=elementType, 450 + name = "[" .. id .. "] " .. base_name, 451 + tableName = base_name, 452 + prefix = prefix, 453 + item_id = item_id, 454 + monitor = false, 455 + screenPos=library.getPointOnScreen(ConvertLocalToWorld(pos, constructPos, constructRight, constructForward, constructUp)), 456 + } 457 + if item_id and prefix then 458 + for _,sprefix in ipairs(storage_prefix) do 459 + if prefix:lower() == sprefix:lower() then 460 + container.monitor = true 461 + container.item = system.getItem(item_id) 462 + break 463 + end 464 + end 465 + end 466 + local container_size = "XS" 467 + local container_empty_mass = 0 468 + local container_volume = 0 469 + local contentQuantity = 0 470 + local percent_fill = 0 471 + if not elementType:lower():find("hub") then 472 + local containerMaxHP = core.getElementMaxHitPointsById(id) 473 + if containerMaxHP > 68000 then 474 + container_size = "XXL" 475 + container_empty_mass = 88410 476 + container_volume = 512000 * (containerProficiencyLvl * 0.1) + 512000 477 + elseif containerMaxHP > 33000 then 478 + container_size = "XL" 479 + container_empty_mass = 44210 480 + container_volume = 256000 * (containerProficiencyLvl * 0.1) + 256000 481 + elseif containerMaxHP > 17000 then 482 + container_size = "L" 483 + container_empty_mass = 14842.7 484 + container_volume = 128000 * (containerProficiencyLvl * 0.1) + 128000 485 + elseif containerMaxHP > 7900 then 486 + container_size = "M" 487 + container_empty_mass = 7421.35 488 + container_volume = 64000 * (containerProficiencyLvl * 0.1) + 64000 489 + elseif containerMaxHP > 900 then 490 + container_size = "S" 491 + container_empty_mass = 1281.31 492 + container_volume = 8000 * (containerProficiencyLvl * 0.1) + 8000 493 + else 494 + container_size = "XS" 495 + container_empty_mass = 229.09 496 + container_volume = 1000 * (containerProficiencyLvl * 0.1) + 1000 497 + end 498 + else 499 + if splitted[3] then 500 + container_size = splitted[3] 501 + end 502 + if splitted[4] then 503 + container_amount = splitted[4] 504 + end 505 + local volume = 0 506 + container_volume_list = {xxl=512000, xl=256000, l=128000, m=64000, s=8000, xs=1000} 507 + container_size = container_size:lower() 508 + if container_volume_list[container_size] then 509 + volume = container_volume_list[container_size] 510 + end 511 + container_volume = (volume * containerProficiencyLvl * 0.1 + volume) 512 + container_empty_mass = 55.8 513 + end 514 + local totalMass = core.getElementMassById(id) 515 + local contentMassKg = totalMass - container_empty_mass 516 + container.totalMass = totalMass 517 + container.emptyMass = container_empty_mass 518 + container.contentMass = contentMassKg 519 + container.maxVolume = container_volume 520 + container.size = container_size 521 + if container.item == nil or container.item.name == "InvalidItem" then 522 + container.percent = 0 523 + container.quantity = 0 524 + else 525 + container.quantity = contentMassKg / (container.item.unitMass - (container.item.unitMass * (containerOptimizationLvl * 0.05))) 526 + container.percent = utils.round((container.item.unitVolume * container.quantity) * 100 / container_volume) 527 + end 528 + storages['i'..id] = container 529 + if index % machinesRefreshedByFrame == 0 then 530 + coroutine.yield(self.loadStorage) 531 + end 532 + end 533 + end 534 + hud.coroutines.renderHelper = function() 535 + local year, month, day, hour, minute, second = DUCurrentDateTime() 536 + html_time = [[<div class="hud_time hud_container"><div style="text-align:center;">]] .. string.format("%02d/%02d/%04d %02d:%02d:%02d",day,month,year,hour,minute,second) .. [[</div><div style="text-align:right;"><hr class="hr-light"><style>.dm]] .. displayMode .. [[{border: 1px solid #28a745 !important;}.dp]] .. displayType .. [[{border: 1px solid #28a745 !important;}.sortType]] .. sortingType .. [[{border: 1px solid #28a745 !important;}</style><div>]] 537 + for i,v in ipairs(sortingTypes) do 538 + html_time = html_time .. '<span class="sortType' .. i ..'" style="margin:5px;">' .. v .. '</span>' 539 + if i < #sortingTypes then html_time = html_time .. "|" end 540 + end 541 + html_time = html_time .. ' - Sorting Type - Alt + 6</div><div>' 542 + for i,v in ipairs(displayTypes) do 543 + html_time = html_time .. '<span class="dp' .. (i-1) .. '" style="margin:5px;">' .. v .. '</span>' 544 + if i < #displayTypes then html_time = html_time .. "|" end 545 + end 546 + html_time = html_time .. ' - Display Type - Alt + 7</div><div>' 547 + for i,v in ipairs(displayModes) do 548 + html_time = html_time .. '<span class="dm' .. (i-1) .. '" style="margin:5px;">' .. v .. '</span>' 549 + if i < #displayModes then html_time = html_time .. "|" end 550 + end 551 + html_time = html_time .. ' - Display Mode - Alt + 8</div>' 552 + html_time = html_time .. '<div>Reload HUD - Alt + 9</div>' 553 + if schematicContainer ~= nil then 554 + html_time = html_time .. '<hr class="hr-light"><div>Schematic Storage Refresh in ' .. schematicRefreshTime .. 's</div>' 555 + end 556 + html_time = html_time .. '</div></div>' 557 + end 558 + hud.coroutines.renderIndustries = function() 559 + local html = "" 560 + local html_table = "" 561 + local lastMachine = 0 562 + local firstMachine = 0 563 + local totalPage = 1 564 + local selectedMachine = nil 565 + if displayMode == 0 or displayMode == 1 then 566 + local selectedIndustries = {} 567 + for k,industry in pairs(industries) do 568 + if (statusFilter == 0 or industry.state == statusFilter) and (statusFilterType == 0 or (statusFilterType <= #elementsTypes and industry.typeFilter:lower() == elementsTypes[statusFilterType])) then 569 + if displayType == 0 then 570 + table.insert(selectedIndustries, industry) 571 + elseif displayType == 1 then 572 + table.insert(selectedIndustries, industry) 573 + elseif displayType == 2 then 574 + if industry.screenPos[1] > 0 and industry.screenPos[1] < 1 and industry.screenPos[2] > 0 and industry.screenPos[2] < 1 then 575 + table.insert(selectedIndustries, industry) 576 + end 577 + end 578 + end 579 + end 580 + if (displayType == 0 or displayType == 1) and statusFilterType <= #elementsTypes then 581 + totalPage = math.ceil(#selectedIndustries/elementsByPage) 582 + firstMachine = (page - 1) * elementsByPage + 1 583 + lastMachine = page * elementsByPage 584 + if lastMachine > #selectedIndustries then 585 + lastMachine = #selectedIndustries 586 + end 587 + html_table = html_table .. '<div class="hud_container hud_table_container"><div style="text-align:center;border-bottom:1px solid white;">&#x2191; &nbsp;&nbsp; Arrow Up</div><table style="width:100%"><tr><th>&#x2190; &nbsp;&nbsp; Arrow Left</th><th> Page ' .. page .. '/' .. totalPage .. ' (from ' .. firstMachine .. ' to ' .. lastMachine .. ' on ' .. #selectedIndustries .. ')</th><th>Arrow Right &nbsp;&nbsp; &#x2192;</th></tr></table><table><tr><th>id</th><th>Machine Name & Type</th><th>Selected Recipe & schematic</th><th>Status</th><th>Mode</th><th>Time Remaining</th></tr>' 588 + end 589 + local count = 1 590 + if sortingType == 1 then 591 + table.sort(selectedIndustries, function(a,b) return a.tableName < b.tableName end) 592 + elseif sortingType == 2 then 593 + table.sort(selectedIndustries, function(a,b) return a.production.locDisplayNameWithSize < b.production.locDisplayNameWithSize end) 594 + elseif sortingType == 3 then 595 + table.sort(selectedIndustries, function(a,b) return a.id < b.id end) 596 + end 597 + for k,industry in pairs(selectedIndustries) do 598 + if (displayType == 0 or displayType == 2) and industry.screenPos[1] > 0 and industry.screenPos[1] < 1 and industry.screenPos[2] > 0 and industry.screenPos[2] < 1 then 599 + local showDetail = false 600 + if industry.screenPos[3] <= machineDetailDisplayDistance then 601 + showDetail = true 602 + elseif industry.screenPos[1] < 0.55 and industry.screenPos[1] > 0.45 and industry.screenPos[2] < 0.55 and industry.screenPos[2] > 0.45 then 603 + showDetail = true 604 + end 605 + local font_size = fontSize * ((200-industry.screenPos[3])/200) 606 + local zindex = utils.round(1000 - industry.screenPos[3]) 607 + html = html .. [[<div class="ib" style="left:]] .. utils.round(industry.screenPos[1]*100) .. [[%;top:]] .. utils.round(industry.screenPos[2]*100) .. [[%;font-size:]] .. font_size .. [[px;z-index:]]..zindex..[[;"><div class="]] .. getIndustryStatusBgClass(industry.state) .. [[" style="padding:2px;text-transform:capitalize;"><span class="tier]] .. industry.production.tier .. [[">T]] .. industry.production.tier .. [[</span><strong>]] .. industry.production.locDisplayNameWithSize .. [[</strong></div>]] 608 + if showDetail then 609 + html = html .. [[<div class="bg-light text-dark" style="margin-top:2px;padding:2px;"><div class="]] .. getIndustryStatusClass(industry.state) .. [["><strong>]] .. statusList[industry.state] .. [[</strong></div><div>]] .. industry.productId .. industry.name .. industry.type .. industry.mode .. industry.schematic .. industry.remainingTime .. industry.recipe ..[[</div></div>]] 610 + end 611 + html = html .. [[</div>]] 612 + end 613 + if (displayType == 0 or displayType == 1) then 614 + local selectedClass = "" 615 + if selectedRow == (count + 1 - firstMachine)then 616 + selectedClass = "row_selected" 617 + selectedMachine = industry 618 + end 619 + if count >= firstMachine and count <= lastMachine then 620 + html_table = html_table .. '<tr><th class="' .. selectedClass .. '">' .. industry.id .. '</th><th class="' .. selectedClass .. '"><span class="' .. getIndustryStatusClass(industry.state) .. '">' .. industry.tableName .. '</span><br><small>' .. industry.tableType .. '</small></th><th class="' .. selectedClass .. '">' .. industry.production.locDisplayNameWithSize .. '<br><small class="text-' .. industry.schematicColor .. '">' .. industry.tableSchematicQuantity .. " " .. industry.tableSchematic .. '</small></th><th class="' .. selectedClass .. '"><span class="' .. getIndustryStatusClass(industry.state) .. '">' .. statusList[industry.state] .. '</span></th><th class="' .. selectedClass .. '">' .. industry.tableMode .. '</th><th class="' .. selectedClass .. '">' .. industry.tableTime .. '</th></tr>' 621 + end 622 + end 623 + count = count + 1 624 + end 625 + if (displayType == 0 or displayType == 1) and statusFilterType <= #elementsTypes then 626 + html_table = html_table .. '</table><table style="width:100%"><tr><th>&#x2190; &nbsp;&nbsp; Arrow Left</th><th> Page ' .. page .. '/' .. totalPage .. ' (from ' .. firstMachine .. ' to ' .. lastMachine .. ' on ' .. #selectedIndustries .. ')</th><th>Arrow Right &nbsp;&nbsp; &#x2192;</th></tr></table><div style="text-align:center;border-bottom:1px solid white;">&#x2193; &nbsp;&nbsp; Arrow Down</div></div>' 627 + maxPage = totalPage 628 + maxOnPage = lastMachine-firstMachine+1 629 + end 630 + end 631 + html_machines = html .. html_table 632 + selected_machine = selectedMachine 633 + end 634 + hud.coroutines.renderStorage = function() 635 + local html = "" 636 + local html_table = "" 637 + local lastStorage = 0 638 + local firstStorage = 0 639 + local totalPage = 1 640 + local selectedStorage = nil 641 + if displayMode == 0 or displayMode == 2 then 642 + local selectedStorages = {} 643 + for k,storage in pairs(storages) do 644 + if statusFilterType >= maxFilterType and storage.monitor then 645 + if displayType == 0 then 646 + table.insert(selectedStorages, storage) 647 + elseif displayType == 1 then 648 + table.insert(selectedStorages, storage) 649 + end 650 + end 651 + end 652 + if (displayType == 0 or displayType == 2) then 653 + for k,storage in pairs(storages) do 654 + if storage.screenPos[1] > 0 and storage.screenPos[1] < 1 and storage.screenPos[2] > 0 and storage.screenPos[2] < 1 then 655 + local showDetail = false 656 + if storage.screenPos[3] <= machineDetailDisplayDistance then 657 + showDetail = true 658 + elseif storage.screenPos[1] < 0.55 and storage.screenPos[1] > 0.45 and storage.screenPos[2] < 0.55 and storage.screenPos[2] > 0.45 then 659 + showDetail = true 660 + end 661 + local font_size = fontSize * ((200-storage.screenPos[3])/200) 662 + local zindex = utils.round(1000 - storage.screenPos[3]) 663 + local displayName = storage.name 664 + local tierBox = '' 665 + local itemBox = '' 666 + local fillGauge = '' 667 + if storage.item ~= nil and storage.item.name ~= "InvalidItem" then 668 + displayName = format_number(utils.round(storage.quantity*100)/100) .. " " .. storage.item.locDisplayNameWithSize .. " (" .. storage.percent .. "%)" 669 + tierBox = '<span class="tier' .. storage.item.tier .. '">T' .. storage.item.tier .. '</span>' 670 + local i = storage.item 671 + local gaugePercent = storage.percent 672 + if storage.percent > 100 then 673 + gaugePercent = 100 674 + end 675 + local r,g,b = getRGBGradient(gaugePercent/100,177,42,42,249,212,123,34,177,76) 676 + r = utils.round(r) 677 + g = utils.round(g) 678 + b = utils.round(b) 679 + itemBox = [[<hr><div><strong>Item ID:</strong> ]] .. i.id .. [[</div><div><strong>Item Name:</strong> ]] .. i.locDisplayNameWithSize .. [[</div><div><strong>Item Unit Mass:</strong> ]] .. i.unitMass .. [[ kg</div><div><strong>Item Unit Volume:</strong> ]] .. i.unitVolume .. [[ m<sup>3</sup></div>]] 680 + fillGauge = '<div style="position:absolute;bottom:0;left:0px;width:' .. gaugePercent .. '%;background-color:rgb(' .. r .. ',' .. g ..',' .. b .. ');height:3px;z-index:' .. (zindex+1) .. ';"></div>' 681 + end 682 + html = html .. [[<div class="ib" style="left:]] .. utils.round(storage.screenPos[1]*100) .. [[%;top:]] .. utils.round(storage.screenPos[2]*100) .. [[%;font-size:]] .. font_size .. [[px;z-index:]]..zindex..[[;"><div class="bg-light text-dark" style="padding:2px;padding-bottom:5px;text-transform:capitalize;position:relative;">]] .. tierBox .. [[<strong>]] .. displayName .. [[</strong>]] .. fillGauge .. [[</div>]] 683 + if showDetail then 684 + html = html .. [[<div class="bg-light text-dark" style="margin-top:2px;padding:2px;"><div><strong>Container Type:</strong> ]] .. storage.type .. " " .. storage.size .. [[</div>]] .. itemBox .. [[</div></div>]] 685 + end 686 + html = html .. [[</div>]] 687 + end 688 + end 689 + end 690 + if (displayType == 0 or displayType == 1) and statusFilterType >= maxFilterType then 691 + totalPage = math.ceil(#selectedStorages/elementsByPage) 692 + firstStorage = (page - 1) * elementsByPage + 1 693 + lastStorage = page * elementsByPage 694 + if lastStorage > #selectedStorages then 695 + lastStorage = #selectedStorages 696 + end 697 + html_table = html_table .. '<div class="hud_container hud_table_container"><div style="text-align:center;border-bottom:1px solid white;">&#x2191; &nbsp;&nbsp; Arrow Up</div><table style="width:100%"><tr><th>&#x2190; &nbsp;&nbsp; Arrow Left</th><th> Page ' .. page .. '/' .. totalPage .. ' (from ' .. firstStorage .. ' to ' .. lastStorage .. ' on ' .. #selectedStorages .. ')</th><th>Arrow Right &nbsp;&nbsp; &#x2192;</th></tr></table><table><tr><th>id</th><th>Storage Name & Type</th><th>Item Name</th><th>Quantity</th><th style="width:100px;">Percent fill</th></tr>' 698 + local count = 1 699 + if sortingType == 1 then 700 + table.sort(selectedStorages, function(a,b) return a.tableName < b.tableName end) 701 + elseif sortingType == 2 then 702 + table.sort(selectedStorages, function(a,b) return a.item.locDisplayNameWithSize < b.item.locDisplayNameWithSize end) 703 + elseif sortingType == 3 then 704 + table.sort(selectedStorages, function(a,b) return a.id < b.id end) 705 + end 706 + for k,storage in pairs(selectedStorages) do 707 + if count >= firstStorage and count <= lastStorage then 708 + local selectedClass = "" 709 + if selectedRow == (count + 1 - firstStorage)then 710 + selectedClass = "row_selected" 711 + selectedStorage = storage 712 + end 713 + local item_name = "" 714 + if storage.item ~= nil and storage.item.name ~= "InvalidItem" then 715 + item_name = storage.item.locDisplayNameWithSize 716 + end 717 + local gaugePercent = storage.percent 718 + if storage.percent > 100 then 719 + gaugePercent = 100 720 + end 721 + local r,g,b = getRGBGradient(gaugePercent/100,177,42,42,249,212,123,34,177,76) 722 + r = utils.round(r) 723 + g = utils.round(g) 724 + b = utils.round(b) 725 + html_table = html_table .. '<tr><th class="' .. selectedClass .. '">' .. storage.id .. '</th><th class="' .. selectedClass .. '">' .. storage.tableName .. '<br><small>' .. storage.type .. ' ' .. storage.size .. '</small></th><th class="' .. selectedClass .. '">' .. item_name .. '</th><th class="' .. selectedClass .. '">' .. format_number(utils.round(storage.quantity*100)/100) .. '</th><th class="' .. selectedClass .. '">' .. storage.percent .. '%<br><div style="border:1px solid black;position:relative;height:5px;"><div style="position:absolute;left:0;top:0;width:' .. gaugePercent .. '%;background-color:rgb(' .. r .. ',' .. g ..',' .. b .. ');height:5px;"></div></div></th></tr>' 726 + end 727 + count = count + 1 728 + end 729 + html_table = html_table .. '</table><table style="width:100%"><tr><th>&#x2190; &nbsp;&nbsp; Arrow Left</th><th> Page ' .. page .. '/' .. totalPage .. ' (from ' .. firstStorage .. ' to ' .. lastStorage .. ' on ' .. #selectedStorages .. ')</th><th>Arrow Right &nbsp;&nbsp; &#x2192;</th></tr></table><div style="text-align:center;border-bottom:1px solid white;">&#x2193; &nbsp;&nbsp; Arrow Down</div></div>' 730 + maxPage = totalPage 731 + maxOnPage = lastStorage-firstStorage+1 732 + end 733 + end 734 + html_storage = html .. html_table 735 + selected_storage = selectedStorage 736 + end 737 + hud.coroutines.renderFilterStatus = function() 738 + html_filters = "<style>" 739 + html_filters = html_filters .. ".bg{margin:5px;padding:2px;}.bg" .. (statusFilter+1) .. "{border: 1px solid #28a745 !important;}" 740 + html_filters = html_filters .. "</style>" 741 + html_filters = html_filters .. [[<div class="hud_container hud_machine_status_container"><div><span class="bg bg1" >ALL</span>|]] 742 + for i,status in ipairs(statusList) do 743 + html_filters = html_filters .. [[<span class="bg bg]] .. (i+1) .. [[ ]] .. getIndustryStatusClass(i) .. [[">]] .. statusList[i] .. [[</span>]] 744 + if i < #statusList then html_filters = html_filters .. '|' end 745 + end 746 + html_filters = html_filters .. '</div>' 747 + html_filters = html_filters .. [[<hr class="hr-light"><table style="width:100%;"><tr><td style="padding-left:5px;">&#x2190; &nbsp;&nbsp; Ctrl+Arrow Left</td><td style="text-align:right;padding-right:5px;">Ctrl+Arrow Right &nbsp;&nbsp; &#x2192;</td></tr></table></div>]] 748 + end 749 + hud.coroutines.renderFilterType = function() 750 + maxFilterType = #elementsTypes 751 + if displayMode == 0 then 752 + maxFilterType = #elementsTypes + 1 753 + elseif displayMode == 2 then 754 + maxFilterType = 0 755 + end 756 + html_filters_types = "<style>" 757 + html_filters_types = html_filters_types .. ".bgt" .. (statusFilterType+1) .. "{border: 2px solid #28a745 !important;}" 758 + html_filters_types = html_filters_types .. "</style>" 759 + html_filters_types = html_filters_types .. '<div class="hud_container hud_machine_types_container" style="text-align:center;"><div>&#x2191; &nbsp;&nbsp; Ctrl+Arrow Up</div><hr class="hr-light">' 760 + if displayMode == 0 or displayMode == 1 then 761 + html_filters_types = html_filters_types .. '<div class="bgt1" style="margin:5px;">ALL Industries (' .. #industries_id .. ')</div>' 762 + for i,v in ipairs(elementsTypes) do 763 + html_filters_types = html_filters_types .. '<div class="bgt' .. (i+1) .. '" style="margin:5px;">' .. v .. ' (' .. machines_count[v] .. ')</div>' 764 + end 765 + end 766 + if displayMode == 0 or displayMode == 2 then 767 + local bgtclass = 'bgt' .. (#elementsTypes + 2) 768 + if displayMode == 2 then 769 + bgtclass = 'bgt1' 770 + end 771 + html_filters_types = html_filters_types .. '<div class="' .. bgtclass .. '" style="margin:5px;">Storage (' .. #storages_id .. ')</div>' 772 + end 773 + html_filters_types = html_filters_types .. '<hr class="hr-light"><div>&#x2193; &nbsp;&nbsp; Ctrl+Arrow Down</div></div>' 774 + end 775 + hud.coroutines.renderSelectedAR = function() 776 + local html = "" 777 + if displayType == 0 or displayType == 1 then 778 + if selected_machine then 779 + local industry = selected_machine 780 + html = html .. [[<div class="ib ]] .. getIndustryStatusBorderClass(industry.state) .. [[" style="border:5px solid white;left:]] .. utils.round(industry.screenPos[1]*100) .. [[%;top:]] .. utils.round(industry.screenPos[2]*100) .. [[%;font-size:]] .. fontSize .. [[px;z-index:1000;"><div class="]] .. getIndustryStatusBgClass(industry.state) .. [[" style="padding:2px;text-transform:capitalize;"><span class="tier]] .. industry.production.tier .. [[">T]] .. industry.production.tier .. [[</span><strong>]] .. industry.production.locDisplayNameWithSize .. [[</strong></div><div class="bg-light text-dark" style="margin-top:2px;padding:2px;"><div class="]] .. getIndustryStatusClass(industry.state) .. [["><strong>]] .. statusList[industry.state] .. [[</strong></div><div>]] .. industry.productId .. industry.name .. industry.type .. industry.mode .. industry.schematic .. industry.remainingTime .. industry.recipe ..[[</div></div></div>]] 781 + elseif selected_storage then 782 + local storage = selected_storage 783 + local displayName = storage.name 784 + local tierBox = '' 785 + local itemBox = '' 786 + local fillGauge = '' 787 + local gaugePercent = storage.percent 788 + if storage.percent > 100 then 789 + gaugePercent = 100 790 + end 791 + local r,g,b = getRGBGradient(gaugePercent/100,177,42,42,249,212,123,34,177,76) 792 + r = utils.round(r) 793 + g = utils.round(g) 794 + b = utils.round(b) 795 + if storage.item ~= nil and storage.item.name ~= "InvalidItem" then 796 + displayName = format_number(utils.round(storage.quantity*100)/100) .. " " .. storage.item.locDisplayNameWithSize .. " (" .. storage.percent .. "%)" 797 + tierBox = '<span class="tier' .. storage.item.tier .. '">T' .. storage.item.tier .. '</span>' 798 + local i = storage.item 799 + 800 + itemBox = [[<hr><div><strong>Item ID:</strong> ]] .. i.id .. [[</div><div><strong>Item Name:</strong> ]] .. i.locDisplayNameWithSize .. [[</div><div><strong>Item Unit Mass:</strong> ]] .. i.unitMass .. [[ kg</div><div><strong>Item Unit Volume:</strong> ]] .. i.unitVolume .. [[ m<sup>3</sup></div>]] 801 + fillGauge = '<div style="position:absolute;bottom:0;left:0px;width:' .. gaugePercent .. '%;background-color:rgb(' .. r .. ',' .. g ..',' .. b .. ');height:3px;z-index:1000;"></div>' 802 + end 803 + html = html .. [[<div class="ib" style="border: 5px solid rgb(]] .. r .. [[,]] .. g ..[[,]] .. b .. [[);left:]] .. utils.round(storage.screenPos[1]*100) .. [[%;top:]] .. utils.round(storage.screenPos[2]*100) .. [[%;font-size:]] .. fontSize .. [[px;z-index:1000;"><div class="bg-light text-dark" style="padding:2px;padding-bottom:5px;text-transform:capitalize;position:relative;">]] .. tierBox .. [[<strong>]] .. displayName .. [[</strong>]] .. fillGauge .. [[</div><div class="bg-light text-dark" style="margin-top:2px;padding:2px;"><div><strong>Container Type:</strong> ]] .. storage.type .. " " .. storage.size .. [[</div>]] .. itemBox .. [[</div></div>]] 804 + html = html .. [[</div>]] 805 + end 806 + end 807 + html_ar_selected = html 808 + end 809 + hud.coroutines.renderControlSelectedIndustry = function() 810 + local html = "" 811 + if #databanks > 0 and emitter ~= nil and selected_machine ~= nil and (displayType == 0 or displayType == 1) then 812 + local industry = selected_machine 813 + html = '<div class="hud_container hud_machine_control" style="text-align:center;"><div class="' .. getIndustryStatusClass(industry.state) .. '">' .. industry.tableName .. '<br><small>' .. statusList[industry.state] .. '</small></div><hr class="hr-light"><div>' .. industry.production.locDisplayNameWithSize .. '</div>' 814 + if industry.state == 1 or industry.state == (#statusList - 1) then 815 + command_1 = "START" 816 + command_2 = "BATCH" 817 + command_3 = "MAINTAIN" 818 + html = html .. '<table style="width:100%;"><tr><th style="text-align:left;width:100px;">START</th><th style="width:100px;"></th><th style="text-align:right;width:100px;">Alt+1</th></tr><tr><th style="text-align:left;">START BATCH</th><th rowspan="2">Quantity:<br>' 819 + local has_quantity = false 820 + for k,v in pairs(craft_quantity_digits) do 821 + if tonumber(v) == nil then v = 0 end 822 + if tonumber(v) > 0 then 823 + has_quantity = true 824 + end 825 + end 826 + if not has_quantity then 827 + local value = tostring(math.floor(industry.maintainOrBatchQuantity)) 828 + for i = #value, 1, -1 do 829 + local c = value:sub(i,i) 830 + craft_quantity_digits[9-(#value-(i-1))] = c 831 + end 832 + end 833 + for digit_index,digit in pairs(craft_quantity_digits) do 834 + html = html .. digit 835 + end 836 + html = html .. '</th><th style="text-align:right;">ALT+2</th></tr><tr><th style="text-align:left;">MAINTAIN</th><th style="text-align:right;">ALT+3</th></tr></table>' 837 + elseif industry.state < #statusList then 838 + command_1 = "STOP" 839 + command_2 = "SOFT_STOP" 840 + command_3 = "HARD_STOP" 841 + html = html .. [[<table><tr><th style="text-align:left;width:250px;">STOP</th><th style="text-align:right;width:50px;">ALT+1</th></tr><tr><th style="text-align:left;">FINISH AND STOP</th><th style="text-align:right;">ALT+2</th></tr><tr><th style="text-align:left;">STOP AND ALLOW MATERIAL LOSS</th><th style="text-align:right;">ALT+3</th></tr></table>]] 842 + else 843 + html = html .. '<div>Pending stop, please wait</div>' 844 + end 845 + html = html .. '</div>' 846 + end 847 + html_control = html 848 + end 849 + hud.coroutines.renderHud = function() 850 + local html = bootstrap_css_colors .. base_css .. html_ar_selected 851 + if displayMode ~= 3 then 852 + html = html .. html_filters_types 853 + if displayMode == 0 or displayMode == 1 then 854 + html = html .. html_machines .. html_filters .. html_control 855 + end 856 + if displayMode == 0 or displayMode == 2 then 857 + html = html .. html_storage 858 + end 859 + end 860 + html = html .. html_time .. html_credits 861 + system.setScreen(html) 862 + end 863 + hud.actions = {} 864 + hud.actions.start = {} 865 + hud.actions.stop = {} 866 + hud.actions.start.brake = function() ctrlPressed = true end 867 + hud.actions.stop.brake = function() ctrlPressed = false end 868 + hud.actions.start.down = function() 869 + if ctrlPressed and displayMode < 3 then 870 + statusFilterType = statusFilterType + 1 871 + if statusFilterType > maxFilterType then statusFilterType = 0 end 872 + onFilterChange() 873 + elseif displayMode < 3 then 874 + selectedRow = selectedRow + 1 875 + if selectedRow > maxOnPage then selectedRow = 1 end 876 + onRowChange() 877 + end 878 + end 879 + hud.actions.start.up = function() 880 + if ctrlPressed and displayMode < 3 then 881 + statusFilterType = statusFilterType - 1 882 + local max = #elementsTypes 883 + if statusFilterType < 0 then statusFilterType = maxFilterType end 884 + onFilterChange() 885 + elseif displayMode < 3 then 886 + selectedRow = selectedRow - 1 887 + if selectedRow < 1 then selectedRow = maxOnPage end 888 + onRowChange() 889 + end 890 + end 891 + hud.actions.start.option1 = function() 892 + if #databanks > 0 and emitter ~= nil and selected_machine ~= nil and (displayType == 0 or displayType == 1) then 893 + --Send Command 1 894 + for _,db in pairs(databanks) do 895 + db.setStringValue(selected_machine.id, command_1) 896 + end 897 + emitter.send(channels[selected_machine.typeFilter:lower()], "") 898 + end 899 + end 900 + hud.actions.start.option2 = function() 901 + if #databanks > 0 and emitter ~= nil and selected_machine ~= nil and (displayType == 0 or displayType == 1) then 902 + --Send Command 2 903 + for _,db in pairs(databanks) do 904 + if command_2:find("MAINTAIN") or command_2:find("BATCH") then 905 + craft_quantity = "" 906 + for _,digit in pairs(craft_quantity_digits) do 907 + craft_quantity = craft_quantity .. digit 908 + end 909 + command_2 = command_2 .. "_" .. craft_quantity 910 + end 911 + db.setStringValue(selected_machine.id, command_2) 912 + if command_2:find("MAINTAIN") then command_2 = "MAINTAIN" end 913 + if command_2:find("BATCH") then command_2 = "BATCH" end 914 + end 915 + emitter.send(channels[selected_machine.typeFilter:lower()], "") 916 + end 917 + end 918 + hud.actions.start.option3 = function() 919 + if #databanks > 0 and emitter ~= nil and selected_machine ~= nil and (displayType == 0 or displayType == 1) then 920 + --Send Command 3 921 + for _,db in pairs(databanks) do 922 + if command_3:find("MAINTAIN") or command_3:find("BATCH") then 923 + craft_quantity = "" 924 + for _,digit in pairs(craft_quantity_digits) do 925 + craft_quantity = craft_quantity .. digit 926 + end 927 + command_3 = command_3 .. "_" .. craft_quantity 928 + end 929 + db.setStringValue(selected_machine.id, command_3) 930 + if command_3:find("MAINTAIN") then command_3 = "MAINTAIN" end 931 + if command_3:find("BATCH") then command_3 = "BATCH" end 932 + end 933 + emitter.send(channels[selected_machine.typeFilter:lower()], "") 934 + end 935 + end 936 + hud.actions.start.option6 = function() 937 + sortingType = sortingType + 1 938 + if sortingType < 0 then sortingType = #sortingTypes end 939 + if sortingType > (#sortingTypes) then sortingType = 1 end 940 + end 941 + hud.actions.start.option7 = function() 942 + displayType = displayType + 1 943 + if displayType < 0 then displayType = (#displayTypes-1) end 944 + if displayType > (#displayTypes-1) then displayType = 0 end 945 + end 946 + hud.actions.start.option8 = function() 947 + displayMode = displayMode + 1 948 + if displayMode < 0 then displayMode = (#displayModes-1) end 949 + if displayMode > (#displayModes-1) then displayMode = 0 end 950 + end 951 + hud.actions.start.option9 = function() 952 + init = false 953 + end 954 + hud.actions.start.strafeleft = function() 955 + if ctrlPressed and (displayMode == 0 or displayMode == 1) then 956 + statusFilter = statusFilter - 1 957 + if statusFilter < 0 then statusFilter = #statusList end 958 + onFilterChange() 959 + elseif (displayType == 0 or displayType == 1) then 960 + page = page - 1 961 + if page < 1 then page = maxPage end 962 + onTablePageChange() 963 + end 964 + end 965 + hud.actions.start.straferight = function() 966 + if ctrlPressed and (displayMode == 0 or displayMode == 1) then 967 + statusFilter = statusFilter + 1 968 + if statusFilter > #statusList then statusFilter = 0 end 969 + onFilterChange() 970 + elseif (displayType == 0 or displayType == 1) then 971 + page = page + 1 972 + if page > maxPage then page = 1 end 973 + onTablePageChange() 974 + end 975 + end 976 + 977 + --[[ 978 + DU-Nested-Coroutines by Jericho 979 + Permit to easier avoid CPU Load Errors 980 + Source available here: https://github.com/Jericho1060/du-nested-coroutines 981 + ]]-- 982 + 983 + coroutinesTable = {} 984 + 985 + function initCoroutines() 986 + for k,f in pairs(hud.coroutines) do 987 + coroutinesTable[k] = coroutine.create(f) 988 + end 989 + end 990 + 991 + initCoroutines() 992 + 993 + for k,f in pairs(coroutinesTable) do system.print(k) end 994 + 995 + runCoroutines = function() 996 + for k,co in pairs(coroutinesTable) do 997 + if coroutine.status(co) == "dead" then 998 + coroutinesTable[k] = coroutine.create(hud.coroutines[k]) 999 + end 1000 + if coroutine.status(co) == "suspended" then 1001 + assert(coroutine.resume(co)) 1002 + end 1003 + end 1004 + end 1005 + 1006 + MainCoroutine = coroutine.create(runCoroutines) 1007 + 1008 + unit.hideWidget() 1009 + 1010 + function onTablePageChange() 1011 + selectedRow = 1 1012 + onRowChange() 1013 + end 1014 + 1015 + function onFilterChange() 1016 + onTablePageChange() 1017 + page = 1 1018 + end 1019 + 1020 + function onRowChange() 1021 + craft_quantity_digits = {"0","0","0","0","0","0","0","0"} 1022 + end
+1
Master Program/source/unit/onStop.lua
··· 1 + Storage.clear()