LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

Storage

Parent
Object
Functions

addFillLevelChangedListeners

Description
Definition
addFillLevelChangedListeners()
Code
539function Storage:addFillLevelChangedListeners(func)
540 table.addElement(self.fillLevelChangedListeners, func)
541end

addLoadingStation

Description
Definition
addLoadingStation()
Code
515function Storage:addLoadingStation(loadingStation)
516 self.loadingStations[loadingStation] = loadingStation
517end

addUnloadingStation

Description
Definition
addUnloadingStation()
Code
503function Storage:addUnloadingStation(station)
504 self.unloadingStations[station] = station
505end

delete

Description
Deleting storage
Definition
delete()
Code
198function Storage:delete()
199 g_messageCenter:unsubscribeAll(self)
200
201 if self.fillPlanes ~= nil then
202 for _, fillPlane in pairs(self.fillPlanes) do
203 fillPlane:delete()
204 end
205 self.fillPlanes = nil
206 end
207
208 Storage:superClass().delete(self)
209end

draw

Description
Draws fillLevels and capacities for all fillTypes at storage root node
Definition
draw()
Code
551function Storage:draw()
552 local debugTable = DebugInfoTable.new()
553 local content = {}
554 for fillType, accepted in pairs(self.fillTypes) do
555 if accepted then
556 table.insert(content, {name=g_fillTypeManager:getFillTypeNameByIndex(fillType), value=string.format("%.3f / %.3f\n", self.fillLevels[fillType] or 0, self.capacities[fillType] or self.capacity or -1)})
557 end
558 end
559
560 debugTable:createWithNodeToCamera(self.rootNode, 1, {{title="Storage (without extensions)", content=content}}, 0.05)
561 g_debugManager:addFrameElement(debugTable)
562end

empty

Description
Definition
empty()
Code
342function Storage:empty()
343 for fillType, _ in pairs(self.fillLevels) do
344 self.fillLevels[fillType] = 0
345 if self.isServer then
346 self:raiseDirtyFlags(self.storageDirtyFlag)
347 end
348 end
349end

farmDestroyed

Description
Definition
farmDestroyed()
Code
527function Storage:farmDestroyed(farmId)
528 if self:getOwnerFarmId() == farmId then
529 for fillType, accepted in pairs(self.fillTypes) do
530 if accepted then
531 self:setFillLevel(0, fillType)
532 end
533 end
534 end
535end

getCapacity

Description
Definition
getCapacity()
Code
391function Storage:getCapacity(fillType)
392 return self.capacities[fillType] or self.capacity
393end

getFillLevel

Description
Returns fill level
Definition
getFillLevel(integer fillType)
Arguments
integerfillTypefill type
Return Values
floatfillLevelfill level
Code
379function Storage:getFillLevel(fillType)
380 return self.fillLevels[fillType] or 0
381end

getFillLevels

Description
Definition
getFillLevels()
Code
385function Storage:getFillLevels()
386 return self.fillLevels
387end

getFreeCapacity

Description
Returns free capacity
Definition
getFreeCapacity(integer fillType)
Arguments
integerfillTypefill type
Return Values
floatfreeCapacityfree capacity
Code
446function Storage:getFreeCapacity(fillType)
447 if self.fillLevels[fillType] == nil then
448 return 0
449 end
450
451 if self.supportsMultipleFillTypes then
452 if self.capacities[fillType] ~= nil then
453 return math.max(self.capacities[fillType] - self.fillLevels[fillType], 0)
454 else
455 local usedCapacity = 0
456 for _, fillLevel in pairs(self.fillLevels) do
457 usedCapacity = usedCapacity + fillLevel
458 end
459
460 return math.max(self.capacity - usedCapacity, 0)
461 end
462 end
463
464 local capacity = self.capacities[fillType] or self.capacity
465 local usedCapacity = 0
466 for usedFillType, usedFillLevel in pairs(self.fillLevels) do
467 if fillType == usedFillType then
468 usedCapacity = usedFillLevel
469 else
470 if usedFillLevel > 0 then
471 return 0
472 end
473 end
474 end
475
476 return math.max(capacity - usedCapacity, 0)
477end

getIsFillTypeSupported

Description
Returns if storage allows fill type
Definition
getIsFillTypeSupported(integer fillType)
Arguments
integerfillTypefill type
Return Values
booleanallowallow fill type
Code
371function Storage:getIsFillTypeSupported(fillType)
372 return self.fillTypes[fillType] == true
373end

getSupportedFillTypes

Description
Definition
getSupportedFillTypes()
Code
481function Storage:getSupportedFillTypes()
482 return self.fillTypes
483end

hourChanged

Description
Called on hour change
Definition
hourChanged()
Code
487function Storage:hourChanged()
488 if self.isServer then
489 local difficultyMultiplier = g_currentMission.missionInfo.buyPriceMultiplier
490 local fillLevelFactor = difficultyMultiplier * self.costsPerFillLevelAndDay / 24
491
492 local costs = 0
493 for _, fillLevel in pairs(self.fillLevels) do
494 costs = costs + fillLevel * fillLevelFactor
495 end
496
497 g_currentMission:addMoney(-costs, self:getOwnerFarmId(), MoneyType.PROPERTY_MAINTENANCE, true)
498 end
499end

load

Description
Load storage attributes from object
Definition
load(table components, table xmlFile, string key, table i3dMappings)
Arguments
tablecomponentscomponents
tablexmlFilexml file object
stringkeyxml key
tablei3dMappingsi3dMappings
Return Values
booleansuccesssuccess
Code
73function Storage:load(components, xmlFile, key, i3dMappings)
74 self.rootNode = xmlFile:getValue(key .. "#node", components[1].node, components, i3dMappings)
75
76 self.costsPerFillLevelAndDay = xmlFile:getValue(key .. "#costsPerFillLevelAndDay") or 0
77 self.capacity = xmlFile:getValue(key .. "#capacity", 100000)
78 self.fillLevelSyncThreshold = xmlFile:getValue(key .. "#fillLevelSyncThreshold", 1) -- sync every liter unless defined differently in xml
79 self.supportsMultipleFillTypes = xmlFile:getValue(key .. "#supportsMultipleFillTypes", true)
80
81 self.capacities = {}
82 self.fillTypes = {}
83 self.fillLevels = {}
84 self.fillLevelsLastSynced = {}
85 self.sortedFillTypes = {}
86
87 local fillTypeCategories = xmlFile:getValue(key .. "#fillTypeCategories")
88 local fillTypeNames = xmlFile:getValue(key .. "#fillTypes")
89 local fillTypes
90
91 if fillTypeCategories ~= nil and fillTypeNames == nil then
92 fillTypes = g_fillTypeManager:getFillTypesByCategoryNames(fillTypeCategories, "Warning: '"..tostring(key).. "' has invalid fillTypeCategory '%s'.")
93 elseif fillTypeCategories == nil and fillTypeNames ~= nil then
94 fillTypes = g_fillTypeManager:getFillTypesByNames(fillTypeNames, "Warning: '"..tostring(key).. "' has invalid fillType '%s'.")
95 end
96
97 if fillTypes ~= nil then
98 for _,fillType in pairs(fillTypes) do
99 self.fillTypes[fillType] = true
100 end
101 end
102
103 xmlFile:iterate(key .. ".capacity", function(_, capacityKey)
104 local fillTypeName = xmlFile:getValue(capacityKey.."#fillType")
105 local fillType = g_fillTypeManager:getFillTypeIndexByName(fillTypeName)
106 if fillType ~= nil then
107 self.fillTypes[fillType] = true
108 local capacity = xmlFile:getValue(capacityKey.. "#capacity", 100000)
109 self.capacities[fillType] = capacity
110 else
111 Logging.xmlWarning(xmlFile, "FillType '%s' not defined for '%s'", fillTypeName, capacityKey)
112 end
113 end)
114
115 if table.size(self.fillTypes) == 0 then
116 Logging.xmlError(xmlFile, "'Storage' entry %s needs either the 'fillTypeCategories', 'fillTypes' attribute or fillType specific capacities.", key)
117 return false
118 end
119
120 for fillType,_ in pairs(self.fillTypes) do
121 table.insert(self.sortedFillTypes, fillType)
122 self.fillLevels[fillType] = 0
123 self.fillLevelsLastSynced[fillType] = 0
124 end
125 table.sort(self.sortedFillTypes)
126
127 local usedCapacity = 0
128 xmlFile:iterate(key .. ".startFillLevel", function(_, fillLevelKey)
129 local fillTypeName = xmlFile:getValue(fillLevelKey.."#fillType")
130 local fillType = g_fillTypeManager:getFillTypeIndexByName(fillTypeName)
131 if fillType ~= nil then
132 if self.fillLevels[fillType] ~= nil then
133 local fillLevel = xmlFile:getValue(fillLevelKey.. "#fillLevel")
134 if self.supportsMultipleFillTypes then
135 if self.capacities[fillType] ~= nil then
136 fillLevel = MathUtil.clamp(fillLevel, 0, self.capacities[fillType])
137 self.fillLevels[fillType] = fillLevel
138 else
139 fillLevel = MathUtil.clamp(fillLevel, 0, self.capacity - usedCapacity)
140 usedCapacity = usedCapacity + fillLevel
141 self.fillLevels[fillType] = fillLevel
142 end
143 else
144 if usedCapacity == 0 then
145 fillLevel = MathUtil.clamp(fillLevel, 0, self.capacities[fillType] or self.capacity)
146 usedCapacity = fillLevel
147 self.fillLevels[fillType] = fillLevel
148 else
149 Logging.xmlWarning(xmlFile, "Failed to set start fill level for '%s' because only one filltype allowed at the same time for '%s'", fillTypeName, fillLevelKey)
150 end
151 end
152 else
153
154 Logging.xmlWarning(xmlFile, "FillType '%s' not supported for '%s'", fillTypeName, fillLevelKey)
155 end
156 else
157 Logging.xmlWarning(xmlFile, "FillType '%s' not defined for '%s'", fillTypeName, fillLevelKey)
158 end
159 end)
160
161 self.fillPlanes = {}
162 xmlFile:iterate(key .. ".fillPlane", function(_, fillPlaneKey)
163 local fillTypeName = xmlFile:getValue(fillPlaneKey .. "#fillType")
164 local fillType = g_fillTypeManager:getFillTypeIndexByName(fillTypeName)
165 if fillType ~= nil then
166 local fillPlane = FillPlane.new()
167 fillPlane:load(components, xmlFile, fillPlaneKey, i3dMappings)
168 self.fillPlanes[fillType] = fillPlane
169 end
170 end)
171
172 self.dynamicFillPlaneBaseNode = xmlFile:getValue(key .. ".dynamicFillPlane#node", nil, components, i3dMappings)
173 if self.dynamicFillPlaneBaseNode ~= nil then
174 local defaultFillTypeName = xmlFile:getValue(key.. ".dynamicFillPlane#defaultFillType")
175 local defaultFillTypeIndex = g_fillTypeManager:getFillTypeIndexByName(defaultFillTypeName) or self.sortedFillTypes[1]
176
177 local fillPlane = FillPlaneUtil.createFromXML(xmlFile, key .. ".dynamicFillPlane", self.dynamicFillPlaneBaseNode, self.capacities[defaultFillTypeIndex] or self.capacity)
178
179 if fillPlane ~= nil then
180 FillPlaneUtil.assignDefaultMaterials(fillPlane)
181 FillPlaneUtil.setFillType(fillPlane, defaultFillTypeIndex)
182
183 self.dynamicFillPlane = fillPlane
184 end
185 end
186
187 self.isExtension = xmlFile:getValue(key .. "#isExtension", false)
188
189 self.storageDirtyFlag = self:getNextDirtyFlag()
190
191 g_messageCenter:subscribe(MessageType.FARM_DELETED, self.farmDestroyed, self)
192
193 return true
194end

loadFromXMLFile

Description
Loading from attributes and nodes
Definition
loadFromXMLFile(integer xmlFile, string key)
Arguments
integerxmlFileid of xml object
stringkeykey
Return Values
booleansuccesssuccess
Code
288function Storage:loadFromXMLFile(xmlFile, key)
289 self:setOwnerFarmId(xmlFile:getValue(key .. "#farmId", AccessHandler.EVERYONE), true)
290
291 -- reset all fillLevels because we only save fillevels > 0
292 for fillTypeIndex, fillLevel in pairs(self.fillLevels) do
293 self.fillLevels[fillTypeIndex] = 0
294 end
295
296 local i = 0
297 while true do
298 local siloKey = string.format(key .. ".node(%d)", i)
299 if not xmlFile:hasProperty(siloKey) then
300 break
301 end
302
303 local fillTypeStr = xmlFile:getValue(siloKey.."#fillType")
304 local fillLevel = math.max(xmlFile:getValue(siloKey.."#fillLevel", 0), 0)
305 local fillTypeIndex = g_fillTypeManager:getFillTypeIndexByName(fillTypeStr)
306
307 if fillTypeIndex ~= nil then
308 if self.fillLevels[fillTypeIndex] ~= nil then
309 self:setFillLevel(fillLevel, fillTypeIndex, nil)
310 else
311 Logging.xmlWarning(xmlFile, "FillType '%s' is not supported by storage", fillTypeStr)
312 end
313 else
314 Logging.xmlWarning(xmlFile, "FillType Invalid filltype '%s'", fillTypeStr)
315 end
316
317 i = i + 1
318 end
319
320 return true
321end

new

Description
Creating new instance of storage class
Definition
new(boolean isServer, boolean isClient)
Arguments
booleanisServeris server
booleanisClientis client
Return Values
tableselfnew instance of object
Code
53function Storage.new(isServer, isClient, customMt)
54 local self = Object.new(isServer, isClient, customMt or Storage_mt)
55
56 self.unloadingStations = {}
57 self.loadingStations = {}
58 self.fillLevelChangedListeners = {}
59
60 self.rootNode = 0
61 self.foreignSilo = false
62
63 return self
64end

readStream

Description
Called on client side on join
Definition
readStream(integer streamId, table connection)
Arguments
integerstreamIdstream ID
tableconnectionconnection
Code
215function Storage:readStream(streamId, connection)
216 Storage:superClass().readStream(self, streamId, connection)
217
218 for _, fillType in ipairs(self.sortedFillTypes) do
219 local fillLevel = 0
220 if streamReadBool(streamId) then
221 fillLevel = streamReadFloat32(streamId)
222 end
223 self:setFillLevel(fillLevel, fillType)
224 end
225end

readUpdateStream

Description
Called on client side on update
Definition
readUpdateStream(integer streamId, integer timestamp, table connection)
Arguments
integerstreamIdstream ID
integertimestamptimestamp
tableconnectionconnection
Code
248function Storage:readUpdateStream(streamId, timestamp, connection)
249 Storage:superClass().readUpdateStream(self, streamId, timestamp, connection)
250 if connection:getIsServer() then
251 if streamReadBool(streamId) then
252 for _, fillType in ipairs(self.sortedFillTypes) do
253 local fillLevel = 0
254 if streamReadBool(streamId) then
255 fillLevel = streamReadFloat32(streamId)
256 end
257 self:setFillLevel(fillLevel, fillType)
258 end
259 end
260 end
261end

registerSavegameXMLPaths

Description
Definition
registerSavegameXMLPaths()
Code
41function Storage.registerSavegameXMLPaths(schema, basePath)
42 schema:register(XMLValueType.INT, basePath .. "#farmId", "Owner farm land id", 0)
43 schema:register(XMLValueType.STRING, basePath .. ".node(?)#fillType", "Fill type name")
44 schema:register(XMLValueType.FLOAT, basePath .. ".node(?)#fillLevel", "Fill level", 0)
45end

registerXMLPaths

Description
Definition
registerXMLPaths()
Code
19function Storage.registerXMLPaths(schema, basePath)
20 schema:register(XMLValueType.NODE_INDEX, basePath .. "#node", "Storage node")
21 schema:register(XMLValueType.FLOAT, basePath .. "#capacity", "Total capacity", 100000)
22 schema:register(XMLValueType.FLOAT, basePath .. "#fillLevelSyncThreshold", "Fill level difference needed for synchronization in Multiplayer", 1)
23 schema:register(XMLValueType.BOOL, basePath .. "#supportsMultipleFillTypes", "If true capacity can be used by multiple fill types at the same time. If false only one filltype is allowed", true)
24 schema:register(XMLValueType.FLOAT, basePath .. "#costsPerFillLevelAndDay", "Costs per fill level and day", 0)
25 schema:register(XMLValueType.STRING, basePath .. "#fillTypeCategories", "Supported fill type categories")
26 schema:register(XMLValueType.STRING, basePath .. "#fillTypes", "Supported fill types")
27 schema:register(XMLValueType.BOOL, basePath .. "#isExtension", "If storage is an extension")
28 schema:register(XMLValueType.STRING, basePath .. ".capacity(?)#fillType", "Custom filltype capacity")
29 schema:register(XMLValueType.FLOAT, basePath .. ".capacity(?)#capacity", "Custom filltype capacity")
30 schema:register(XMLValueType.STRING, basePath .. ".startFillLevel(?)#fillType", "Start filllevel fill type")
31 schema:register(XMLValueType.FLOAT, basePath .. ".startFillLevel(?)#fillLevel", "Start filllevel")
32 FillPlane.registerXMLPaths(schema, basePath .. ".fillPlane(?)")
33 schema:register(XMLValueType.STRING, basePath .. ".fillPlane(?)#fillType", "Fillplane till type")
34
35 FillPlaneUtil.registerFillPlaneXMLPaths(schema, basePath .. ".dynamicFillPlane")
36 schema:register(XMLValueType.STRING, basePath .. ".dynamicFillPlane#defaultFillType", "Fillplane default filltype")
37end

removeFillLevelChangedListeners

Description
Definition
removeFillLevelChangedListeners()
Code
545function Storage:removeFillLevelChangedListeners(func)
546 table.removeElement(self.fillLevelChangedListeners, func)
547end

removeLoadingStation

Description
Definition
removeLoadingStation()
Code
521function Storage:removeLoadingStation(loadingStation)
522 self.loadingStations[loadingStation] = nil
523end

removeUnloadingStation

Description
Definition
removeUnloadingStation()
Code
509function Storage:removeUnloadingStation(station)
510 self.unloadingStations[station] = nil
511end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
325function Storage:saveToXMLFile(xmlFile, key, usedModNames)
326 xmlFile:setValue(key.."#farmId", self:getOwnerFarmId())
327
328 local index = 0
329 for fillTypeIndex, fillLevel in pairs(self.fillLevels) do
330 if fillLevel > 0 then
331 local fillLevelKey = string.format("%s.node(%d)", key, index)
332 local fillTypeName = g_fillTypeManager:getFillTypeNameByIndex(fillTypeIndex)
333 xmlFile:setValue(fillLevelKey.."#fillType", fillTypeName)
334 xmlFile:setValue(fillLevelKey.."#fillLevel", fillLevel)
335 index = index + 1
336 end
337 end
338end

setFillLevel

Description
Set fill level of storage
Definition
setFillLevel(float fillLevel, integer fillType, table fillInfo)
Arguments
floatfillLevelnew fill level
integerfillTypefill type
tablefillInfofill info table
Code
400function Storage:setFillLevel(fillLevel, fillType, fillInfo)
401 local capacity = self.capacities[fillType] or self.capacity
402 fillLevel = MathUtil.clamp(fillLevel, 0, capacity)
403 if self.fillLevels[fillType] ~= nil and fillLevel ~= self.fillLevels[fillType] then
404 local oldLevel = self.fillLevels[fillType]
405 self.fillLevels[fillType] = fillLevel
406
407 local delta = self.fillLevels[fillType] - oldLevel
408 if math.abs(delta) > 0.1 then
409 for _, func in ipairs(self.fillLevelChangedListeners) do
410 func(fillType, delta)
411 end
412 end
413
414 if self.isServer then
415 if (fillLevel < 0.1) or (math.abs(self.fillLevelsLastSynced[fillType] - fillLevel) >= self.fillLevelSyncThreshold) or (capacity - fillLevel < 0.1) then
416 self:raiseDirtyFlags(self.storageDirtyFlag)
417 end
418 end
419
420 self:updateFillPlanes()
421
422 if self.dynamicFillPlane ~= nil then
423 local refNode = self.dynamicFillPlane
424 local width, length = 1, 1
425 if fillInfo ~= nil then
426 refNode = fillInfo.node
427 length = fillInfo.length
428 width = fillInfo.width
429 end
430 local x,y,z = localToWorld(refNode, 0,0,0)
431 local d1x,d1y,d1z = localDirectionToWorld(refNode, width, 0, 0)
432 local d2x,d2y,d2z = localDirectionToWorld(refNode, 0, 0, length)
433
434 local steps = MathUtil.clamp(math.floor(delta/400), 1, 25)
435 for _=1, steps do
436 fillPlaneAdd(self.dynamicFillPlane, delta/steps, x,y,z, d1x,d1y,d1z, d2x,d2y,d2z)
437 end
438 end
439 end
440end

updateFillPlanes

Description
Definition
updateFillPlanes()
Code
353function Storage:updateFillPlanes()
354 if self.fillPlanes ~= nil then
355 for fillType, fillPlane in pairs(self.fillPlanes) do
356 local fillLevel = self.fillLevels[fillType]
357 local capacity = self:getCapacity(fillType)
358 local factor = 1
359 if capacity > 0 then
360 factor = fillLevel / capacity
361 end
362 fillPlane:setState(factor)
363 end
364 end
365end

writeStream

Description
Called on server side on join
Definition
writeStream(integer streamId, table connection)
Arguments
integerstreamIdstream ID
tableconnectionconnection
Code
231function Storage:writeStream(streamId, connection)
232 Storage:superClass().writeStream(self, streamId, connection)
233
234 for _, fillType in ipairs(self.sortedFillTypes) do
235 local fillLevel = self.fillLevels[fillType]
236 if streamWriteBool(streamId, fillLevel > 0) then
237 streamWriteFloat32(streamId, fillLevel)
238 self.fillLevelsLastSynced[fillType] = fillLevel
239 end
240 end
241end

writeUpdateStream

Description
Called on server side on update
Definition
writeUpdateStream(integer streamId, table connection, integer dirtyMask)
Arguments
integerstreamIdstream ID
tableconnectionconnection
integerdirtyMaskdirty mask
Code
268function Storage:writeUpdateStream(streamId, connection, dirtyMask)
269 Storage:superClass().writeUpdateStream(self, streamId, connection, dirtyMask)
270 if not connection:getIsServer() then
271 if streamWriteBool(streamId, bitAND(dirtyMask, self.storageDirtyFlag) ~= 0) then
272 for _, fillType in ipairs(self.sortedFillTypes) do
273 local fillLevel = self.fillLevels[fillType]
274 if streamWriteBool(streamId, fillLevel > 0) then
275 streamWriteFloat32(streamId, fillLevel)
276 self.fillLevelsLastSynced[fillType] = fillLevel
277 end
278 end
279 end
280 end
281end