LUADOC - Farming Simulator 22

Script v1_7_1_0

Engine v1_7_1_0

Foundation Reference

PlaceableTrainSystem

Description
Specialization for placeables
Functions

addSplinePositionUpdateListener

Description
Definition
addSplinePositionUpdateListener()
Code
766function PlaceableTrainSystem:addSplinePositionUpdateListener(listener)
767 if listener ~= nil then
768 local spec = self.spec_trainSystem
769 table.addElement(spec.splinePositionUpdateListener, listener)
770 end
771end

createVehicles

Description
Definition
createVehicles()
Code
621function PlaceableTrainSystem:createVehicles()
622 local spec = self.spec_trainSystem
623 if spec.vehicleIdsToLoad ~= nil and #spec.vehicleIdsToLoad > 0 then
624 for k, id in ipairs(spec.vehicleIdsToLoad) do
625 local vehicle = g_currentMission.savegameIdToVehicle[id]
626 if vehicle ~= nil then
627 if vehicle.setTrainSystem == nil then
628--#debug Logging.devWarning("Vehicle '%s' (savegameId %d) is not a railroad vehicle", vehicle:getName(), id)
629--#debug printCallstack()
630 else
631 vehicle:setTrainSystem(self)
632 vehicle.trainVehicleIndex = k
633 table.insert(spec.railroadVehicles, vehicle)
634 end
635 end
636 end
637
638 self:finalizeTrain(false)
639 else
640 for k, filename in ipairs(spec.vehiclesToLoad) do
641 filename = Utils.getFilename(filename, spec.baseDirectory)
642 spec.numVehiclesToLoad = spec.numVehiclesToLoad + 1
643
644 local arguments = {
645 filename = filename,
646 vehicleIndex = k
647 }
648 VehicleLoadingUtil.loadVehicle(filename, {x=0, z=0, yOffset=0}, true, 0, Vehicle.PROPERTY_STATE_NONE, AccessHandler.EVERYONE, nil, nil, spec.railroadVehicleLoaded, self, arguments)
649 end
650
651 end
652 spec.vehiclesToLoad = {}
653end

finalizeTrain

Description
Definition
finalizeTrain()
Code
678function PlaceableTrainSystem:finalizeTrain(attachVehicles)
679 local spec = self.spec_trainSystem
680
681 table.sort(spec.railroadVehicles, function(a, b)
682 return a.trainVehicleIndex < b.trainVehicleIndex
683 end)
684
685 local lastVehicle = nil
686 spec.rootLocomotive = nil
687 for _,railroadVehicle in ipairs(spec.railroadVehicles) do
688 railroadVehicle:addDeleteListener(self)
689
690 if spec.rootLocomotive == nil and railroadVehicle.startAutomatedTrainTravel ~= nil then
691 spec.rootLocomotive = railroadVehicle
692 end
693
694 if attachVehicles and lastVehicle ~= nil then
695 lastVehicle:attachImplement(railroadVehicle, 1, 1, true)
696 end
697
698 lastVehicle = railroadVehicle
699 end
700
701 self:updateTrainLength(spec.startSplineTime)
702 self:setIsTrainTabbable(spec.isRented and g_currentMission:getFarmId() == spec.rentFarmId)
703end

getCanBeRented

Description
Definition
getCanBeRented()
Code
895function PlaceableTrainSystem:getCanBeRented(farmId)
896 local spec = self.spec_trainSystem
897
898 if spec.isRented then
899 if spec.rentFarmId ~= farmId then
900 return false
901 end
902 end
903
904 return true
905end

getElectricitySpline

Description
Definition
getElectricitySpline()
Code
925function PlaceableTrainSystem:getElectricitySpline()
926 local spec = self.spec_trainSystem
927 return spec.electricitySpline
928end

getElectricitySplineLength

Description
Definition
getElectricitySplineLength()
Code
932function PlaceableTrainSystem:getElectricitySplineLength()
933 local spec = self.spec_trainSystem
934 return spec.electricitySplineLength or 0
935end

getIsRented

Description
Definition
getIsRented()
Code
888function PlaceableTrainSystem:getIsRented()
889 local spec = self.spec_trainSystem
890 return spec.isRented
891end

getIsTrainInDriveableRange

Description
Definition
getIsTrainInDriveableRange()
Code
725function PlaceableTrainSystem:getIsTrainInDriveableRange()
726 return self.spec_trainSystem.lastIsInDriveableRange
727end

getLengthSplineTime

Description
Definition
getLengthSplineTime()
Code
945function PlaceableTrainSystem:getLengthSplineTime()
946 local spec = self.spec_trainSystem
947 return spec.trainLengthSplineTime
948end

getNeedDayChanged

Description
Definition
getNeedDayChanged()
Code
939function PlaceableTrainSystem:getNeedDayChanged(superFunc)
940 return true
941end

getSpline

Description
Definition
getSpline()
Code
952function PlaceableTrainSystem:getSpline()
953 local spec = self.spec_trainSystem
954 return spec.spline
955end

getSplineLength

Description
Definition
getSplineLength()
Code
918function PlaceableTrainSystem:getSplineLength()
919 local spec = self.spec_trainSystem
920 return spec.splineLength
921end

getSplineTime

Description
Definition
getSplineTime()
Code
731function PlaceableTrainSystem:getSplineTime()
732 return self.spec_trainSystem.splineTime
733end

gsIsTrainFilled

Description
Definition
gsIsTrainFilled()
Code
1032function PlaceableTrainSystem:gsIsTrainFilled()
1033 local spec = self.spec_trainSystem
1034 for _,railroadVehicle2 in ipairs(spec.railroadVehicles) do
1035 if railroadVehicle2.getFillUnits ~= nil then
1036 local fillUnits = railroadVehicle2:getFillUnits()
1037 for fillUnitIndex, fillUnit in ipairs(fillUnits) do
1038 if fillUnit.fillLevel > 0 then
1039 return true
1040 end
1041 end
1042 end
1043 end
1044
1045 return false
1046end

loadFromXMLFile

Description
Definition
loadFromXMLFile()
Code
440function PlaceableTrainSystem:loadFromXMLFile(xmlFile, key)
441 local spec = self.spec_trainSystem
442
443 xmlFile:iterate(key .. ".railroadObjects", function(_, railroadKey)
444 local index = xmlFile:getValue(railroadKey.."#index")
445 if index ~= nil then
446 local object = spec.railroadObjects[index]
447 if object ~= nil then
448 object:loadFromXMLFile(xmlFile, railroadKey)
449 end
450 end
451 end)
452
453 spec.isRented = xmlFile:getValue(key.."#isRented", spec.isRented)
454 spec.rentFarmId = xmlFile:getValue(key.."#rentFarmId", spec.rentFarmId)
455 spec.lastRentFarmId = spec.rentFarmId
456 spec.currentPrice = xmlFile:getValue(key.."#currentPrice", spec.currentPrice)
457
458 spec.startSplineTime = SplineUtil.getValidSplineTime(xmlFile:getValue(key.."#splineTime") or 0)
459
460 spec.vehicleIdsToLoad = {}
461 local i = 0
462 while true do
463 local vehicleKey = string.format("%s.railroadVehicle(%d)", key, i)
464 if not xmlFile:hasProperty(vehicleKey) then
465 break
466 end
467
468 local vehicleId = xmlFile:getValue(vehicleKey.."#vehicleId")
469 if vehicleId ~= nil then
470 table.insert(spec.vehicleIdsToLoad, vehicleId)
471 end
472
473 i = i + 1
474 end
475end

onDayChanged

Description
Definition
onDayChanged()
Code
875function PlaceableTrainSystem:onDayChanged()
876 if self.isServer then
877 local spec = self.spec_trainSystem
878 if spec.currentPrice > 0 then
879 g_currentMission:addMoney(-spec.currentPrice, spec.rentFarmId, MoneyType.LEASING_COSTS, true)
880 g_currentMission:showMoneyChange(MoneyType.LEASING_COSTS, nil, false, spec.rentFarmId)
881 spec.currentPrice = 0
882 end
883 end
884end

onDelete

Description
Definition
onDelete()
Code
290function PlaceableTrainSystem:onDelete()
291 local spec = self.spec_trainSystem
292
293 if spec.railroadObjects ~= nil then
294 for _, object in ipairs(spec.railroadObjects) do
295 object:delete()
296 end
297 end
298
299 if spec.railroadVehicles ~= nil then
300 for _, vehicle in ipairs(spec.railroadVehicles) do
301 vehicle.trainSystem = nil
302 end
303 end
304
305 g_currentMission:removeTrainSystem(self)
306end

onDeleteObject

Description
Definition
onDeleteObject()
Code
909function PlaceableTrainSystem:onDeleteObject(object)
910 local spec = self.spec_trainSystem
911 if table.removeElement(spec.railroadVehicles, object) then
912 self:updateTrainLength(spec.splineTime)
913 end
914end

onFinalizePlacement

Description
Definition
onFinalizePlacement()
Code
310function PlaceableTrainSystem:onFinalizePlacement()
311 local spec = self.spec_trainSystem
312
313 if spec.railroadCrossings ~= nil then
314 for _, railroadCrossing in ipairs(spec.railroadCrossings) do
315 railroadCrossing:findBlockingPositions()
316 end
317 end
318
319 for _, object in ipairs(spec.railroadObjects) do
320 if object.setSplineTimeByPosition ~= nil then
321 object:setSplineTimeByPosition(object.nearestTime, spec.splineLength)
322 end
323 if object.onSplinePositionTimeUpdate ~= nil then
324 object:onSplinePositionTimeUpdate(spec.splineTime, spec.splineEndTime)
325 end
326 end
327
328 g_currentMission:addTrainSystem(self)
329
330 if g_currentMission.isMissionStarted then
331 self:createVehicles()
332 else
333 g_messageCenter:subscribeOneshot(MessageType.LOADED_ALL_SAVEGAME_VEHICLES, self.createVehicles, self, {})
334 end
335end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
116function PlaceableTrainSystem:onLoad(savegame)
117 local spec = self.spec_trainSystem
118
119 spec.splineTime = -1
120 spec.splineTimeSent = spec.splineTime
121 spec.splineEndTime = 0
122 spec.trainLengthSplineTime = 0
123 spec.splinePositionUpdateListener = {}
124 spec.startSplineTime = spec.startSplineTime or 0
125 spec.railroadVehicles = {}
126 spec.trainLength = 0
127 spec.dirtyFlag = self:getNextDirtyFlag()
128 spec.stationDirtyFlag = self:getNextDirtyFlag()
129 spec.networkTimeInterpolator = InterpolationTime.new(1.2)
130 spec.networkSplineTimeInterpolator = InterpolatorValue.new(0)
131
132 spec.isRented = false
133 spec.rentFarmId = FarmManager.SPECTATOR_FARM_ID
134 spec.lastRentFarmId = FarmManager.SPECTATOR_FARM_ID
135 spec.currentPrice = 0
136 spec.rentPricePerHour = self.xmlFile:getValue("placeable.trainSystem.rent#pricePerHour", 0)
137 spec.rentPricePerMS = spec.rentPricePerHour / 60 / 60 / 1000
138
139 spec.rootLocomotive = nil
140
141 spec.spline = self.xmlFile:getValue("placeable.trainSystem.spline#node", nil, self.components, self.i3dMappings)
142 if spec.spline == nil then
143 Logging.xmlError(self.xmlFile, "Missing spline node!")
144 self:setLoadingState(Placeable.LOADING_STATE_ERROR)
145 return
146 end
147
148 if not getHasClassId(getGeometry(spec.spline), ClassIds.SPLINE) then
149 Logging.xmlError(self.xmlFile, "Given node is not a spline!")
150 self:setLoadingState(Placeable.LOADING_STATE_ERROR)
151 return
152 end
153
154 if not getIsSplineClosed(spec.spline) then
155 Logging.xmlError(self.xmlFile, "Train spline is not closed. Open splines are not supported!")
156 self:setLoadingState(Placeable.LOADING_STATE_ERROR)
157 return
158 end
159
160 spec.splineLength = getSplineLength(spec.spline)
161 spec.splineYOffset = self.xmlFile:getValue("placeable.trainSystem.spline#splineYOffset", 0.0)
162
163 spec.splineDriveRange = {0, 1}
164
165 spec.drivingRangeStart = self.xmlFile:getValue("placeable.trainSystem.drivingRange#startNode", nil, self.components, self.i3dMappings)
166 spec.drivingRangeEnd = self.xmlFile:getValue("placeable.trainSystem.drivingRange#endNode", nil, self.components, self.i3dMappings)
167 spec.drivingRangeSellingStationId = self.xmlFile:getValue("placeable.trainSystem.drivingRange#sellingStationId")
168
169 spec.textDriveInfo = g_i18n:getText("ui_infoTrainDrive")
170 spec.textSellQuestion = g_i18n:getText("ui_questionTrainSellGoods")
171
172 spec.hasLimitedRange = false
173 if spec.drivingRangeStart ~= nil and spec.drivingRangeEnd ~= nil then
174 local nearestDistanceStart = math.huge
175 local nearestDistanceEnd = math.huge
176 for i=0, 1, 0.5 / spec.splineLength do
177 local sx, sy, sz = getSplinePosition(spec.spline, i)
178
179 local x1, y1, z1 = getWorldTranslation(spec.drivingRangeStart)
180 local distance1 = MathUtil.vector3Length(sx-x1, sy-y1, sz-z1)
181 if distance1 < nearestDistanceStart then
182 nearestDistanceStart = distance1
183 spec.splineDriveRange[1] = i
184 end
185
186 local x2, y2, z2 = getWorldTranslation(spec.drivingRangeEnd)
187 local distance2 = MathUtil.vector3Length(sx-x2, sy-y2, sz-z2)
188 if distance2 < nearestDistanceEnd then
189 nearestDistanceEnd = distance2
190 spec.splineDriveRange[2] = i
191 end
192 end
193
194 if spec.splineDriveRange[1] > spec.splineDriveRange[2] then
195 local secondValue = spec.splineDriveRange[2]
196 spec.splineDriveRange[2] = spec.splineDriveRange[1]
197 spec.splineDriveRange[1] = secondValue
198 end
199
200 spec.hasLimitedRange = true
201 end
202
203 spec.sellingStationPlaceable = nil
204 spec.sellingStationPlaceableId = nil
205 spec.sellingStation = nil
206 spec.showDialog = 0
207 spec.showDialogDelay = 0
208
209 spec.lastIsInDriveableRange = true
210 spec.lastSplineTime = 0
211
212 spec.electricitySpline = self.xmlFile:getValue("placeable.trainSystem.electricitySpline#node", nil, self.components, self.i3dMappings)
213 if spec.electricitySpline ~= nil then
214 if getHasClassId(getGeometry(spec.electricitySpline), ClassIds.SPLINE) then
215 if getIsSplineClosed(spec.electricitySpline) then
216 local sx, _, sz = getSplinePosition(spec.spline, 0)
217 local esx, _, esz = getSplinePosition(spec.spline, 0)
218 if MathUtil.vector2Length(sx-esx, sz-esz) < 5 then
219 spec.electricitySplineLength = getSplineLength(spec.electricitySpline)
220 spec.electricitySplineYOffset = self.xmlFile:getValue("placeable.trainSystem.electricitySpline#splineYOffset", 0.0)
221 else
222 Logging.xmlError(self.xmlFile, "Railroad and electricity spline should almost start at the same x and z positions. Ignoring electricity spline!")
223 spec.electricitySpline = nil
224 end
225 else
226 Logging.xmlError(self.xmlFile, "Railroad electricity spline has to be closed. Ignoring electricity spline!")
227 spec.electricitySpline = nil
228 end
229 else
230 Logging.xmlError(self.xmlFile, "Given electricitySpline node is not a spline. Ignoring electricity spline!")
231 spec.electricitySpline = nil
232 end
233 end
234
235 spec.vehiclesToLoad = {}
236
237 if self.isServer then
238 self.xmlFile:iterate("placeable.trainSystem.train.vehicle", function(_, baseString)
239 local filename = self.xmlFile:getValue(baseString .. "#xmlFilename")
240 if filename ~= nil then
241 table.insert(spec.vehiclesToLoad, filename)
242 end
243 end)
244 end
245
246 spec.railroadObjects = {}
247 spec.railroadCrossings = {}
248 self.xmlFile:iterate("placeable.trainSystem.railroadCrossings.railroadCrossing", function(_, key)
249 local railroadCrossing = RailroadCrossing.new(self.isServer, self.isClient, self, self.rootNode)
250 if railroadCrossing:loadFromXML(self.xmlFile, key, self.components, self.i3dMappings) then
251 table.insert(spec.railroadCrossings, railroadCrossing)
252 table.insert(spec.railroadObjects, railroadCrossing)
253 else
254 railroadCrossing:delete()
255 end
256 end)
257
258 spec.railroadCallers = {}
259 self.xmlFile:iterate("placeable.trainSystem.railroadCallers.railroadCaller", function(_, key)
260 local railroadCaller = RailroadCaller.new(self.isServer, self.isClient, self, self.rootNode)
261 if railroadCaller:loadFromXML(self.xmlFile, key, self.components, self.i3dMappings) then
262 table.insert(spec.railroadCallers, railroadCaller)
263 table.insert(spec.railroadObjects, railroadCaller)
264 end
265 end)
266
267 for t=0, 1, 0.5/spec.splineLength do
268 local x1, y1, z1 = getSplinePosition(spec.spline, t)
269 for _, object in ipairs(spec.railroadObjects) do
270 local x2, y2, z2 = getWorldTranslation(object.rootNode)
271 local distance = MathUtil.vector3Length(x1-x2, y1-y2, z1-z2)
272 if object.nearestDistance == nil then
273 object.nearestDistance = distance
274 object.nearestTime = t
275 else
276 if object.nearestDistance > distance then
277 object.nearestDistance = distance
278 object.nearestTime = t
279 end
280 end
281 end
282 end
283
284 spec.lastVehicle = nil
285 spec.numVehiclesToLoad = 0
286end

onReadStream

Description
Definition
onReadStream()
Code
339function PlaceableTrainSystem:onReadStream(streamId, connection)
340 if connection:getIsServer() then
341 local spec = self.spec_trainSystem
342 spec.railroadVehicleIds = {}
343 local numVehicles = streamReadInt8(streamId)
344 for i=1,numVehicles do
345 spec.railroadVehicleIds[i] = NetworkUtil.readNodeObjectId(streamId)
346 end
347
348 local splineTime = streamReadFloat32(streamId)
349 spec.networkSplineTimeInterpolator:setValue(splineTime)
350 spec.networkTimeInterpolator:reset()
351 spec.splineTime = splineTime
352
353 for _, railroadObject in ipairs(spec.railroadObjects) do
354 if railroadObject.readStream ~= nil then
355 railroadObject:readStream(streamId, connection)
356 end
357 end
358
359 spec.isRented = streamReadBool(streamId)
360 spec.rentFarmId = streamReadUIntN(streamId, FarmManager.FARM_ID_SEND_NUM_BITS)
361
362 spec.sellingStationPlaceableId = NetworkUtil.readNodeObjectId(streamId)
363
364 self:raiseActive()
365 end
366end

onReadUpdateStream

Description
Definition
onReadUpdateStream()
Code
396function PlaceableTrainSystem:onReadUpdateStream(streamId, timestamp, connection)
397 local spec = self.spec_trainSystem
398 if connection:getIsServer() then
399 if streamReadBool(streamId) then
400 local splineTime = streamReadFloat32(streamId)
401 spec.networkTimeInterpolator:startNewPhaseNetwork()
402 spec.networkSplineTimeInterpolator:setTargetValue(splineTime)
403
404 for _, railroadObject in ipairs(spec.railroadObjects) do
405 if railroadObject.readUpdateStream ~= nil then
406 railroadObject:readUpdateStream(streamId, timestamp, connection)
407 end
408 end
409 end
410
411 if streamReadBool(streamId) then
412 spec.sellingStationPlaceableId = NetworkUtil.readNodeObjectId(streamId)
413 end
414 end
415end

onSellGoodsQuestion

Description
Definition
onSellGoodsQuestion()
Code
1050function PlaceableTrainSystem:onSellGoodsQuestion(yes)
1051 if yes then
1052 g_client:getServerConnection():sendEvent(PlaceableTrainSystemSellEvent.new(self))
1053 end
1054end

onUpdate

Description
Definition
onUpdate()
Code
504function PlaceableTrainSystem:onUpdate(dt)
505 local spec = self.spec_trainSystem
506
507 if not self.finishedFirstUpdate then
508 self:setIsTrainTabbable(spec.isRented and g_currentMission:getFarmId() == spec.rentFarmId)
509
510 self.finishedFirstUpdate = true
511 end
512
513 for _, railroadObject in ipairs(spec.railroadObjects) do
514 if railroadObject.update ~= nil then
515 railroadObject:update(dt)
516 end
517 end
518
519 if spec.isRented then
520 spec.currentPrice = spec.currentPrice + spec.rentPricePerMS * dt
521 end
522
523 if not self.isServer and self.isClient then
524 -- load railroadVehicles on client side
525 if spec.railroadVehicleIds ~= nil then
526 local allVehiclesSynchronized = true
527 for index, id in pairs(spec.railroadVehicleIds) do
528 local vehicle = NetworkUtil.getObject(id)
529 if vehicle == nil or not vehicle:getIsSynchronized() then
530 allVehiclesSynchronized = false
531 end
532 end
533
534 if allVehiclesSynchronized then
535 spec.rootLocomotive = nil
536
537 for index, id in pairs(spec.railroadVehicleIds) do
538 local vehicle = NetworkUtil.getObject(id)
539 if vehicle ~= nil then
540 vehicle:setTrainSystem(self)
541 spec.trainLength = spec.trainLength + vehicle:getFrontToBackDistance()
542 spec.trainLengthSplineTime = spec.trainLength / spec.splineLength
543 table.insert(spec.railroadVehicles, index, vehicle)
544
545 if spec.rootLocomotive == nil and vehicle.startAutomatedTrainTravel ~= nil then
546 spec.rootLocomotive = vehicle
547 end
548 end
549 spec.railroadVehicleIds[index] = nil
550 end
551 if next(spec.railroadVehicleIds) == nil then
552 spec.railroadVehicleIds = nil
553 self:setIsTrainTabbable(spec.isRented and g_currentMission:getFarmId() == spec.rentFarmId)
554 end
555 end
556 end
557
558 -- update train position on client
559 spec.networkTimeInterpolator:update(dt)
560 local interpolationAlpha = spec.networkTimeInterpolator:getAlpha()
561 local splineTime = spec.networkSplineTimeInterpolator:getInterpolatedValue(interpolationAlpha)
562 splineTime = SplineUtil.getValidSplineTime(splineTime)
563 self:updateTrainPositionByLocomotiveSplinePosition(splineTime)
564 end
565
566 if spec.hasLimitedRange then
567 if spec.sellingStationPlaceable == nil then
568 if spec.drivingRangeSellingStationId ~= nil then
569 for _, placeable in pairs(g_currentMission.placeableSystem.placeables) do
570 if placeable.mapBoundId == spec.drivingRangeSellingStationId then
571 if placeable.spec_sellingStation ~= nil then
572 spec.sellingStationPlaceable = placeable
573 spec.sellingStation = placeable.spec_sellingStation.sellingStation
574
575 self:raiseDirtyFlags(spec.stationDirtyFlag)
576 end
577 end
578 end
579
580 spec.drivingRangeSellingStationId = nil
581 end
582 end
583
584 if spec.sellingStationPlaceable == nil and spec.sellingStationPlaceableId ~= nil then
585 local placeable = NetworkUtil.getObject(spec.sellingStationPlaceableId)
586 if placeable ~= nil then
587 if placeable.spec_sellingStation ~= nil then
588 spec.sellingStationPlaceable = placeable
589 spec.sellingStation = placeable.spec_sellingStation.sellingStation
590 end
591 end
592 end
593
594 if spec.showDialogDelay > 0 then
595 spec.showDialogDelay = spec.showDialogDelay - dt
596 if spec.showDialogDelay <= 0 then
597 local stationName = "UNKNOWN"
598 if spec.sellingStationPlaceable ~= nil then
599 stationName = spec.sellingStationPlaceable:getName()
600 end
601
602 local textDriveInfo = string.format(spec.textDriveInfo, stationName)
603 local textSellQuestion = string.format(spec.textSellQuestion, stationName)
604
605 if spec.showDialog == 2 then
606 g_gui:showYesNoDialog({text=textDriveInfo .. "\n\n" .. textSellQuestion, callback=self.onSellGoodsQuestion, target=self})
607 else
608 g_gui:showInfoDialog({text=textDriveInfo})
609 end
610
611 spec.showDialog = 0
612 end
613 end
614 end
615
616 self:raiseActive()
617end

onWriteStream

Description
Definition
onWriteStream()
Code
370function PlaceableTrainSystem:onWriteStream(streamId, connection)
371 if not connection:getIsServer() then
372 local spec = self.spec_trainSystem
373 local numVehicles = #spec.railroadVehicles
374 streamWriteInt8(streamId, numVehicles)
375 for i=1,numVehicles do
376 NetworkUtil.writeNodeObject(streamId, spec.railroadVehicles[i])
377 end
378
379 streamWriteFloat32(streamId, spec.splineTimeSent)
380
381 for _, railroadObject in ipairs(spec.railroadObjects) do
382 if railroadObject.writeStream ~= nil then
383 railroadObject:writeStream(streamId, connection)
384 end
385 end
386
387 streamWriteBool(streamId, spec.isRented)
388 streamWriteUIntN(streamId, spec.rentFarmId, FarmManager.FARM_ID_SEND_NUM_BITS)
389
390 NetworkUtil.writeNodeObject(streamId, spec.sellingStationPlaceable)
391 end
392end

onWriteUpdateStream

Description
Definition
onWriteUpdateStream()
Code
419function PlaceableTrainSystem:onWriteUpdateStream(streamId, connection, dirtyMask)
420 local spec = self.spec_trainSystem
421 if not connection:getIsServer() then
422 if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then
423 streamWriteFloat32(streamId, spec.splineTimeSent)
424
425 for _, railroadObject in ipairs(spec.railroadObjects) do
426 if railroadObject.writeUpdateStream ~= nil then
427 railroadObject:writeUpdateStream(streamId, connection, dirtyMask)
428 end
429 end
430 end
431
432 if streamWriteBool(streamId, bitAND(dirtyMask, spec.stationDirtyFlag) ~= 0) then
433 NetworkUtil.writeNodeObject(streamId, spec.sellingStationPlaceable)
434 end
435 end
436end

prerequisitesPresent

Description
Checks if all prerequisite specializations are loaded
Definition
prerequisitesPresent(table specializations)
Arguments
tablespecializationsspecializations
Return Values
booleanhasPrerequisitetrue if all prerequisite specializations are loaded
Code
20function PlaceableTrainSystem.prerequisitesPresent(specializations)
21 return true
22end

railroadVehicleLoaded

Description
Definition
railroadVehicleLoaded()
Code
657function PlaceableTrainSystem:railroadVehicleLoaded(vehicle, vehicleLoadState, args)
658 local filename = args.filename
659 local vehicleIndex = args.vehicleIndex
660
661 local spec = self.spec_trainSystem
662 if vehicle ~= nil and vehicleLoadState == VehicleLoadingUtil.VEHICLE_LOAD_OK then
663 vehicle:setTrainSystem(self)
664 vehicle.trainVehicleIndex = vehicleIndex
665 table.insert(spec.railroadVehicles, vehicle)
666 else
667 Logging.warning("(%s) Could not create trainsystem vehicle!", filename)
668 end
669
670 spec.numVehiclesToLoad = spec.numVehiclesToLoad - 1
671 if spec.numVehiclesToLoad == 0 and #spec.vehiclesToLoad == 0 then
672 self:finalizeTrain(true)
673 end
674end

registerEventListeners

Description
Definition
registerEventListeners()
Code
64function PlaceableTrainSystem.registerEventListeners(placeableType)
65 SpecializationUtil.registerEventListener(placeableType, "onLoad", PlaceableTrainSystem)
66 SpecializationUtil.registerEventListener(placeableType, "onDelete", PlaceableTrainSystem)
67 SpecializationUtil.registerEventListener(placeableType, "onFinalizePlacement", PlaceableTrainSystem)
68 SpecializationUtil.registerEventListener(placeableType, "onReadStream", PlaceableTrainSystem)
69 SpecializationUtil.registerEventListener(placeableType, "onWriteStream", PlaceableTrainSystem)
70 SpecializationUtil.registerEventListener(placeableType, "onReadUpdateStream", PlaceableTrainSystem)
71 SpecializationUtil.registerEventListener(placeableType, "onWriteUpdateStream", PlaceableTrainSystem)
72 SpecializationUtil.registerEventListener(placeableType, "onUpdate", PlaceableTrainSystem)
73 SpecializationUtil.registerEventListener(placeableType, "onDayChanged", PlaceableTrainSystem)
74end

registerFunctions

Description
Definition
registerFunctions()
Code
26function PlaceableTrainSystem.registerFunctions(placeableType)
27 SpecializationUtil.registerFunction(placeableType, "createVehicles", PlaceableTrainSystem.createVehicles)
28 SpecializationUtil.registerFunction(placeableType, "railroadVehicleLoaded", PlaceableTrainSystem.railroadVehicleLoaded)
29 SpecializationUtil.registerFunction(placeableType, "finalizeTrain", PlaceableTrainSystem.finalizeTrain)
30 SpecializationUtil.registerFunction(placeableType, "setIsTrainTabbable", PlaceableTrainSystem.setIsTrainTabbable)
31 SpecializationUtil.registerFunction(placeableType, "getIsTrainInDriveableRange", PlaceableTrainSystem.getIsTrainInDriveableRange)
32 SpecializationUtil.registerFunction(placeableType, "getSplineTime", PlaceableTrainSystem.getSplineTime)
33 SpecializationUtil.registerFunction(placeableType, "setSplineTime", PlaceableTrainSystem.setSplineTime)
34 SpecializationUtil.registerFunction(placeableType, "addSplinePositionUpdateListener", PlaceableTrainSystem.addSplinePositionUpdateListener)
35 SpecializationUtil.registerFunction(placeableType, "removeSplinePositionUpdateListener", PlaceableTrainSystem.removeSplinePositionUpdateListener)
36 SpecializationUtil.registerFunction(placeableType, "updateTrainPositionByLocomotiveSpeed", PlaceableTrainSystem.updateTrainPositionByLocomotiveSpeed)
37 SpecializationUtil.registerFunction(placeableType, "updateTrainPositionByLocomotiveSplinePosition", PlaceableTrainSystem.updateTrainPositionByLocomotiveSplinePosition)
38 SpecializationUtil.registerFunction(placeableType, "updateTrainLength", PlaceableTrainSystem.updateTrainLength)
39 SpecializationUtil.registerFunction(placeableType, "toggleRent", PlaceableTrainSystem.toggleRent)
40 SpecializationUtil.registerFunction(placeableType, "getCanBeRented", PlaceableTrainSystem.getCanBeRented)
41 SpecializationUtil.registerFunction(placeableType, "rentRailroad", PlaceableTrainSystem.rentRailroad)
42 SpecializationUtil.registerFunction(placeableType, "returnRailroad", PlaceableTrainSystem.returnRailroad)
43 SpecializationUtil.registerFunction(placeableType, "onDeleteObject", PlaceableTrainSystem.onDeleteObject)
44 SpecializationUtil.registerFunction(placeableType, "getIsRented", PlaceableTrainSystem.getIsRented)
45 SpecializationUtil.registerFunction(placeableType, "getSplineLength", PlaceableTrainSystem.getSplineLength)
46 SpecializationUtil.registerFunction(placeableType, "getElectricitySpline", PlaceableTrainSystem.getElectricitySpline)
47 SpecializationUtil.registerFunction(placeableType, "getElectricitySplineLength", PlaceableTrainSystem.getElectricitySplineLength)
48 SpecializationUtil.registerFunction(placeableType, "getLengthSplineTime", PlaceableTrainSystem.getLengthSplineTime)
49 SpecializationUtil.registerFunction(placeableType, "getSpline", PlaceableTrainSystem.getSpline)
50 SpecializationUtil.registerFunction(placeableType, "updateDriveableState", PlaceableTrainSystem.updateDriveableState)
51 SpecializationUtil.registerFunction(placeableType, "gsIsTrainFilled", PlaceableTrainSystem.gsIsTrainFilled)
52 SpecializationUtil.registerFunction(placeableType, "onSellGoodsQuestion", PlaceableTrainSystem.onSellGoodsQuestion)
53 SpecializationUtil.registerFunction(placeableType, "sellGoods", PlaceableTrainSystem.sellGoods)
54end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
58function PlaceableTrainSystem.registerOverwrittenFunctions(placeableType)
59 SpecializationUtil.registerOverwrittenFunction(placeableType, "getNeedDayChanged", PlaceableTrainSystem.getNeedDayChanged)
60end

registerSavegameXMLPaths

Description
Definition
registerSavegameXMLPaths()
Code
102function PlaceableTrainSystem.registerSavegameXMLPaths(schema, basePath)
103 schema:setXMLSpecializationType("Train")
104 schema:register(XMLValueType.FLOAT, basePath .. "#splineTime", "Current spline time")
105 schema:register(XMLValueType.BOOL, basePath .. "#isRented", "Is train rented")
106 schema:register(XMLValueType.INT, basePath .. "#rentFarmId", "Train is rented by farm")
107 schema:register(XMLValueType.FLOAT, basePath .. "#currentPrice", "Current pending rent price")
108 schema:register(XMLValueType.INT, basePath .. ".railroadVehicle(?)#vehicleId", "Vehicle id")
109 schema:register(XMLValueType.INT, basePath .. ".railroadObjects(?)#index", "Object index")
110 schema:setXMLSpecializationType()
111end

registerXMLPaths

Description
Definition
registerXMLPaths()
Code
78function PlaceableTrainSystem.registerXMLPaths(schema, basePath)
79 schema:setXMLSpecializationType("Train")
80 schema:register(XMLValueType.FLOAT, basePath .. ".trainSystem.rent#pricePerHour", "Rent price per real time hour", 0)
81
82 schema:register(XMLValueType.NODE_INDEX, basePath .. ".trainSystem.spline#node", "Spline node")
83 schema:register(XMLValueType.FLOAT, basePath .. ".trainSystem.spline#splineYOffset", "Spline Y offset", 0)
84
85 schema:register(XMLValueType.NODE_INDEX, basePath .. ".trainSystem.drivingRange#startNode", "Start of range node")
86 schema:register(XMLValueType.NODE_INDEX, basePath .. ".trainSystem.drivingRange#endNode", "End of range node")
87 schema:register(XMLValueType.STRING, basePath .. ".trainSystem.drivingRange#sellingStationId", "Map bound id of selling station")
88
89 schema:register(XMLValueType.NODE_INDEX, basePath .. ".trainSystem.electricitySpline#node", "Electricity spline")
90 schema:register(XMLValueType.FLOAT, basePath .. ".trainSystem.electricitySpline#splineYOffset", "Electricity spline Y offset", 0)
91
92 schema:register(XMLValueType.STRING, basePath .. ".trainSystem.train.vehicle(?)#xmlFilename", "XMl filename")
93
94 RailroadCrossing.registerXMLPaths(schema, basePath .. ".trainSystem.railroadCrossings.railroadCrossing(?)")
95 RailroadCaller.registerXMLPaths(schema, basePath .. ".trainSystem.railroadCallers.railroadCaller(?)")
96
97 schema:setXMLSpecializationType()
98end

removeSplinePositionUpdateListener

Description
Definition
removeSplinePositionUpdateListener()
Code
775function PlaceableTrainSystem:removeSplinePositionUpdateListener(listener)
776 if listener ~= nil then
777 local spec = self.spec_trainSystem
778 table.removeElement(spec.splinePositionUpdateListener, listener)
779 end
780end

rentRailroad

Description
Definition
rentRailroad()
Code
829function PlaceableTrainSystem:rentRailroad(farmId, position, noEventSend)
830 local spec = self.spec_trainSystem
831 spec.isRented = true
832
833 spec.rentFarmId = farmId
834 spec.lastRentFarmId = farmId
835 spec.rootLocomotive:setRequestedSplinePosition(position)
836
837 for _, railroadVehicle in ipairs(spec.railroadVehicles) do
838 railroadVehicle:setOwnerFarmId(spec.rentFarmId, true)
839 end
840
841 self:setIsTrainTabbable(g_currentMission:getFarmId() == farmId)
842
843 PlaceableTrainSystemRentEvent.sendEvent(self, true, farmId, position, noEventSend)
844end

returnRailroad

Description
Definition
returnRailroad()
Code
848function PlaceableTrainSystem:returnRailroad(noEventSend)
849 local spec = self.spec_trainSystem
850 spec.isRented = false
851
852 if self.isServer then
853 if spec.currentPrice > 0 then
854 g_currentMission:addMoney(-spec.currentPrice, spec.rentFarmId, MoneyType.LEASING_COSTS, true)
855 g_currentMission:showMoneyChange(MoneyType.LEASING_COSTS, nil, false, spec.rentFarmId)
856 spec.currentPrice = 0
857 end
858
859 spec.rootLocomotive:startAutomatedTrainTravel()
860 end
861
862 spec.rentFarmId = FarmManager.SPECTATOR_FARM_ID
863
864 for _, railroadVehicle in ipairs(spec.railroadVehicles) do
865 railroadVehicle:setOwnerFarmId(spec.rentFarmId, true)
866 end
867
868 self:setIsTrainTabbable(false)
869
870 PlaceableTrainSystemRentEvent.sendEvent(self, false, nil, nil, noEventSend)
871end

saveToXMLFile

Description
Definition
saveToXMLFile()
Code
479function PlaceableTrainSystem:saveToXMLFile(xmlFile, key, usedModNames)
480 local spec = self.spec_trainSystem
481
482 xmlFile:setValue(key.."#splineTime", SplineUtil.getValidSplineTime(spec.splineTime))
483
484 for k, railroadVehicle in ipairs(spec.railroadVehicles) do
485 local railroadKey = string.format("%s.railroadVehicle(%d)", key, k-1)
486 xmlFile:setValue(railroadKey.."#vehicleId", railroadVehicle.currentSavegameId or 0)
487 end
488
489 for k, railroadObject in ipairs(spec.railroadObjects) do
490 local railroadKey = string.format("%s.railroadObjects(%d)", key, k-1)
491 if railroadObject.saveToXMLFile ~= nil then
492 xmlFile:setValue(railroadKey.."#index", k)
493 railroadObject.saveToXMLFile(xmlFile, railroadKey, usedModNames)
494 end
495 end
496
497 xmlFile:setValue(key.."#isRented", spec.isRented)
498 xmlFile:setValue(key.."#rentFarmId", spec.rentFarmId)
499 xmlFile:setValue(key.."#currentPrice", spec.currentPrice)
500end

sellGoods

Description
Definition
sellGoods()
Code
1058function PlaceableTrainSystem:sellGoods()
1059 local spec = self.spec_trainSystem
1060 if spec.sellingStation ~= nil and spec.rentFarmId ~= 0 then
1061 local soldDelta = 0
1062 for _,railroadVehicle in ipairs(spec.railroadVehicles) do
1063 if railroadVehicle.getFillUnits ~= nil then
1064 local fillUnits = railroadVehicle:getFillUnits()
1065 for fillUnitIndex, fillUnit in ipairs(fillUnits) do
1066 local delta = spec.sellingStation:addFillLevelFromTool(spec.rentFarmId, fillUnit.fillLevel, fillUnit.fillType, nil, ToolType.UNDEFINED)
1067 railroadVehicle:addFillUnitFillLevel(railroadVehicle:getOwnerFarmId(), fillUnitIndex, -delta, fillUnit.fillType, ToolType.UNDEFINED, nil)
1068 soldDelta = soldDelta + delta
1069 end
1070 end
1071 end
1072
1073 -- if we've sold something we return the train
1074 if soldDelta > 0 then
1075 if spec.isRented then
1076 self:returnRailroad()
1077 end
1078 end
1079 end
1080end

setIsTrainTabbable

Description
Definition
setIsTrainTabbable()
Code
707function PlaceableTrainSystem:setIsTrainTabbable(isTabbable)
708 local spec = self.spec_trainSystem
709
710 isTabbable = isTabbable and g_gameSettings:getValue("isTrainTabbable")
711
712 if spec.hasLimitedRange then
713 isTabbable = isTabbable and spec.lastIsInDriveableRange
714 end
715
716 for _,railroadVehicle in ipairs(spec.railroadVehicles) do
717 if railroadVehicle.setIsTabbable ~= nil then
718 railroadVehicle:setIsTabbable(isTabbable)
719 end
720 end
721end

setSplineTime

Description
Definition
setSplineTime()
Code
737function PlaceableTrainSystem:setSplineTime(startTime, endTime)
738 local spec = self.spec_trainSystem
739 if startTime ~= spec.splineTime then
740 if spec.hasLimitedRange then
741 self:updateDriveableState(startTime)
742 end
743
744 local t1 = SplineUtil.getValidSplineTime(startTime)
745 for _,railroadVehicle in ipairs(spec.railroadVehicles) do
746 t1 = railroadVehicle:alignToSplineTime(spec.spline, spec.splineYOffset, t1)
747 end
748 for _,listener in ipairs(spec.splinePositionUpdateListener) do
749 listener:onSplinePositionTimeUpdate(startTime, endTime)
750 end
751 spec.splineTime = startTime
752 spec.splineEndTime = endTime
753
754 if self.isServer then
755 local threshold = 0.02 / spec.splineLength -- 2 cm threshold
756 if math.abs(spec.splineTime-spec.splineTimeSent) > threshold then
757 spec.splineTimeSent = spec.splineTime
758 self:raiseDirtyFlags(spec.dirtyFlag)
759 end
760 end
761 end
762end

toggleRent

Description
Definition
toggleRent()
Code
815function PlaceableTrainSystem:toggleRent(farmId, position)
816 local spec = self.spec_trainSystem
817
818 if spec.isRented then
819 if spec.rentFarmId == farmId then
820 self:returnRailroad()
821 end
822 else
823 self:rentRailroad(farmId, position, false)
824 end
825end

updateDriveableState

Description
Definition
updateDriveableState()
Code
959function PlaceableTrainSystem:updateDriveableState(newSplineTime)
960 local spec = self.spec_trainSystem
961
962 local isInDriveableRange = (newSplineTime % 1) >= spec.splineDriveRange[1] and (newSplineTime % 1) <= spec.splineDriveRange[2]
963 if isInDriveableRange ~= spec.lastIsInDriveableRange then
964 spec.lastIsInDriveableRange = isInDriveableRange
965 if not isInDriveableRange then
966 for _,railroadVehicle in ipairs(spec.railroadVehicles) do
967 if self.isClient then
968 if railroadVehicle.getIsEntered ~= nil and railroadVehicle:getIsEntered() then
969 g_currentMission:onLeaveVehicle()
970
971 -- show a bit delayed so the player is positionated correctly
972 spec.showDialogDelay = 100
973 spec.showDialog = 1
974 if self:gsIsTrainFilled() then
975 spec.showDialog = 2
976 end
977 end
978 end
979
980 if self.isServer then
981 local locomotiveSpec = railroadVehicle.spec_locomotive
982 if locomotiveSpec ~= nil then
983 if locomotiveSpec.state ~= Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE
984 and locomotiveSpec.state ~= Locomotive.STATE_REQUESTED_POSITION
985 and locomotiveSpec.state ~= Locomotive.STATE_REQUESTED_POSITION_BRAKING then
986 railroadVehicle:setLocomotiveState(Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE)
987
988 -- return rental if train is empty so user will not pay for the drive outside of the map
989 if not self:gsIsTrainFilled() then
990 if spec.isRented then
991 self:returnRailroad()
992 end
993 end
994
995 if spec.splineTime < newSplineTime then
996 locomotiveSpec.sellingDirection = 1
997 else
998 locomotiveSpec.sellingDirection = -1
999 end
1000 end
1001 end
1002 end
1003 end
1004 else
1005 if self.isServer then
1006 for _,railroadVehicle in ipairs(spec.railroadVehicles) do
1007 local locomotiveSpec = railroadVehicle.spec_locomotive
1008 if locomotiveSpec ~= nil then
1009 if not railroadVehicle:getIsReadyForAutomatedTrainTravel() then
1010 if locomotiveSpec.state == Locomotive.STATE_AUTOMATIC_TRAVEL_ACTIVE then
1011 railroadVehicle:setLocomotiveState(Locomotive.STATE_MANUAL_TRAVEL_INACTIVE)
1012 locomotiveSpec.sellingDirection = 1
1013 end
1014 else
1015 if locomotiveSpec.sellingDirection ~= nil and locomotiveSpec.sellingDirection < 0 then
1016 locomotiveSpec.sellingDirection = 1
1017
1018 railroadVehicle:setLocomotiveState(Locomotive.STATE_MANUAL_TRAVEL_INACTIVE)
1019 end
1020 end
1021 end
1022 end
1023 end
1024 end
1025
1026 self:setIsTrainTabbable(spec.isRented and g_currentMission:getFarmId() == spec.rentFarmId)
1027 end
1028end

updateTrainLength

Description
Definition
updateTrainLength()
Code
804function PlaceableTrainSystem:updateTrainLength(splinePosition)
805 local spec = self.spec_trainSystem
806 for _,railroadVehicle in ipairs(spec.railroadVehicles) do
807 spec.trainLength = spec.trainLength + railroadVehicle:getFrontToBackDistance()
808 end
809 spec.trainLengthSplineTime = spec.trainLength / spec.splineLength
810 self:updateTrainPositionByLocomotiveSplinePosition(splinePosition)
811end

updateTrainPositionByLocomotiveSpeed

Description
Definition
updateTrainPositionByLocomotiveSpeed()
Code
784function PlaceableTrainSystem:updateTrainPositionByLocomotiveSpeed(dt, speed)
785 local spec = self.spec_trainSystem
786 local distance = speed * (dt / 1000)
787 local increment = distance / spec.splineLength
788 local splineTime = self:getSplineTime() + increment
789
790 self:setSplineTime(splineTime, splineTime-spec.trainLengthSplineTime)
791end

updateTrainPositionByLocomotiveSplinePosition

Description
Definition
updateTrainPositionByLocomotiveSplinePosition()
Code
795function PlaceableTrainSystem:updateTrainPositionByLocomotiveSplinePosition(splinePosition)
796 local spec = self.spec_trainSystem
797 local splineTime = splinePosition
798
799 self:setSplineTime(splineTime, splineTime-spec.trainLengthSplineTime)
800end