276 | function LivestockTrailer:addAnimal(animal) |
277 | local spec = self.spec_livestockTrailer |
278 | local success, _ = ListUtil.addElementToList(spec.loadedAnimals, animal) |
279 | if success then |
280 | spec.currentAnimalType = animal:getSubType().type |
281 | |
282 | spec.loadedAnimalsIds[NetworkUtil.getObjectId(animal)] = true |
283 | spec.animalToSlots[animal] = {} |
284 | |
285 | local place = spec.animalTypeToPlaces[animal.subType.type] |
286 | for _, slot in ipairs(place.slots) do |
287 | if slot.loadedMesh == nil then |
288 | local animalMeshRoot = g_i3DManager:loadSharedI3DFile(animal.subType.dummy.filename) |
289 | local animalRoot = getChildAt(animalMeshRoot, 0) |
290 | local animalMesh = I3DUtil.indexToObject(animalMeshRoot, animal.subType.dummy.meshNodeStr) |
291 | local animalHairMesh = I3DUtil.indexToObject(animalMeshRoot, animal.subType.dummy.hairNodeStr) |
292 | |
293 | link(slot.linkNode, animalRoot) |
294 | delete(animalMeshRoot) |
295 | |
296 | -- set dirt |
297 | local x, y, z, w = getShaderParameter(animalMesh, "RDT") |
298 | local dirt = animal:getDirtScale() |
299 | setShaderParameter(animalMesh, "RDT", x, dirt, z, w, false) |
300 | |
301 | -- set texture |
302 | local x, y, _, _ = getShaderParameter(animalMesh, "atlasInvSizeAndOffsetUV") |
303 | |
304 | local numTilesU = 1 / x |
305 | local numTilesV = 1 / y |
306 | local subType = animal:getSubType() |
307 | local tileUIndex = subType.texture.tileUIndex |
308 | local tileVIndex = subType.texture.tileVIndex |
309 | local tileU = tileUIndex / numTilesU |
310 | local tileV = tileVIndex / numTilesV |
311 | |
312 | setShaderParameter(animalMesh, "atlasInvSizeAndOffsetUV", x, y, tileU, tileV, false) |
313 | |
314 | if animalHairMesh ~= nil then |
315 | local x, y, _, _ = getShaderParameter(animalHairMesh, "atlasInvSizeAndOffsetUV") |
316 | setShaderParameter(animalHairMesh, "atlasInvSizeAndOffsetUV", x, y, tileU, tileV, false) |
317 | end |
318 | |
319 | slot.loadedMesh = animalRoot |
320 | |
321 | table.insert(spec.animalToSlots[animal], slot) |
322 | |
323 | place.numUsed = place.numUsed + 1 |
324 | |
325 | break |
326 | end |
327 | end |
328 | |
329 | self:setMassDirty() |
330 | |
331 | if self.isServer then |
332 | self:raiseDirtyFlags(spec.dirtyFlag) |
333 | end |
334 | end |
335 | end |
15 | function LivestockTrailer.initSpecialization() |
16 | g_storeManager:addSpecType("numAnimalsCow", "shopListAttributeIconCow", LivestockTrailer.loadSpecValueNumberAnimalsCow, LivestockTrailer.getSpecValueNumberAnimalsCow) |
17 | g_storeManager:addSpecType("numAnimalsPig", "shopListAttributeIconPig", LivestockTrailer.loadSpecValueNumberAnimalsPig, LivestockTrailer.getSpecValueNumberAnimalsPig) |
18 | g_storeManager:addSpecType("numAnimalsSheep", "shopListAttributeIconSheep", LivestockTrailer.loadSpecValueNumberAnimalsSheep, LivestockTrailer.getSpecValueNumberAnimalsSheep) |
19 | g_storeManager:addSpecType("numAnimalsHorse", "shopListAttributeIconHorse", LivestockTrailer.loadSpecValueNumberAnimalsHorse, LivestockTrailer.getSpecValueNumberAnimalsHorse) |
20 | end |
63 | function LivestockTrailer:onLoad(savegame) |
64 | local spec = self.spec_livestockTrailer |
65 | |
66 | spec.animalPlaces = {} |
67 | spec.animalTypeToPlaces = {} |
68 | local i = 0 |
69 | while true do |
70 | local key = string.format("vehicle.livestockTrailer.animal(%d)", i) |
71 | if not hasXMLProperty(self.xmlFile, key) then |
72 | break |
73 | end |
74 | |
75 | local place = {} |
76 | place.numUsed = 0 |
77 | |
78 | local animalTypeStr = getXMLString(self.xmlFile, key .. "#type") |
79 | local animalType = g_animalManager:getAnimalsByType(animalTypeStr) |
80 | if animalType == nil then |
81 | g_logManager:xmlWarning(self.configFileName, "Animal type '%s' could not be found!", animalTypeStr) |
82 | break |
83 | end |
84 | place.animalType = animalType.type |
85 | |
86 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key.."#index", key.."#node") --FS17 to FS19 |
87 | |
88 | place.slots = {} |
89 | local parent = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key .. "#node"), self.i3dMappings) |
90 | local numSlots = math.abs(getXMLInt(self.xmlFile, key.."#numSlots") or 0) |
91 | if numSlots > getNumOfChildren(parent) then |
92 | g_logManager:xmlWarning(self.configFileName, "numSlots is greater than available children for '%s'", key) |
93 | numSlots = getNumOfChildren(parent) |
94 | end |
95 | for j=0, numSlots-1 do |
96 | local slotNode = getChildAt(parent, j) |
97 | table.insert(place.slots, {linkNode=slotNode, loadedMesh=nil, place=place}) |
98 | end |
99 | |
100 | table.insert(spec.animalPlaces, place) |
101 | spec.animalTypeToPlaces[place.animalType] = place |
102 | |
103 | i = i + 1 |
104 | end |
105 | |
106 | spec.loadedAnimals = {} |
107 | spec.loadedAnimalsIds = {} |
108 | spec.animalToSlots = {} |
109 | spec.animalsToLoad = nil |
110 | spec.loadingTrigger = nil |
111 | |
112 | spec.currentAnimalType = nil |
113 | |
114 | spec.dirtyFlag = self:getNextDirtyFlag() |
115 | end |
119 | function LivestockTrailer:onLoadFinished(savegame) |
120 | local spec = self.spec_livestockTrailer |
121 | |
122 | if savegame ~= nil and not savegame.resetVehicles then |
123 | local key = string.format("%s.livestockTrailer", savegame.key) |
124 | local i = 0 |
125 | local xmlFile = savegame.xmlFile |
126 | while true do |
127 | local slotKey = string.format("%s.animal(%d)", key, i) |
128 | if not hasXMLProperty(xmlFile, slotKey) then |
129 | break |
130 | end |
131 | |
132 | local animal = Animal.createFromXMLFile(xmlFile, slotKey, self.isServer, self.isClient, nil) |
133 | animal:register() |
134 | self:addAnimal(animal) |
135 | |
136 | i = i + 1 |
137 | end |
138 | end |
139 | end |
189 | function LivestockTrailer:onReadUpdateStream(streamId, timestamp, connection) |
190 | |
191 | if connection:getIsServer() then |
192 | local spec = self.spec_livestockTrailer |
193 | |
194 | if streamReadBool(streamId) then |
195 | local numAnimals = streamReadUInt8(streamId) |
196 | local currentAnimalIds = {} |
197 | |
198 | if spec.animalsToLoad == nil then |
199 | spec.animalsToLoad = {} |
200 | end |
201 | |
202 | for i=1, numAnimals do |
203 | local animalId = NetworkUtil.readNodeObjectId(streamId) |
204 | |
205 | -- add new animals |
206 | if spec.loadedAnimalsIds[animalId] == nil then |
207 | table.insert(spec.animalsToLoad, animalId) |
208 | end |
209 | currentAnimalIds[animalId] = true |
210 | end |
211 | |
212 | -- remove not loaded animals again |
213 | for i=#spec.loadedAnimals, 1, -1 do |
214 | local animal = spec.loadedAnimals[i] |
215 | local animalId = NetworkUtil.getObjectId(animal) |
216 | |
217 | if animalId == nil or currentAnimalIds[animalId] == nil then |
218 | self:removeAnimal(animal) |
219 | end |
220 | end |
221 | end |
222 | end |
223 | end |
242 | function LivestockTrailer:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
243 | local spec = self.spec_livestockTrailer |
244 | if spec.animalsToLoad ~= nil then |
245 | for i=#spec.animalsToLoad, 1, -1 do |
246 | local animalId = spec.animalsToLoad[i] |
247 | local animal = NetworkUtil.getObject(animalId) |
248 | if animal ~= nil then |
249 | self:addAnimal(animal) |
250 | table.remove(spec.animalsToLoad, i) |
251 | end |
252 | end |
253 | |
254 | if #spec.animalsToLoad == 0 then |
255 | spec.animalsToLoad = nil |
256 | end |
257 | end |
258 | end |
227 | function LivestockTrailer:onWriteUpdateStream(streamId, connection, dirtyMask) |
228 | if not connection:getIsServer() then |
229 | local spec = self.spec_livestockTrailer |
230 | |
231 | if streamWriteBool(streamId, bitAND(dirtyMask, spec.dirtyFlag) ~= 0) then |
232 | streamWriteUInt8(streamId, #spec.loadedAnimals) |
233 | for _, animal in ipairs(spec.loadedAnimals) do |
234 | NetworkUtil.writeNodeObject(streamId, animal) |
235 | end |
236 | end |
237 | end |
238 | end |
50 | function LivestockTrailer.registerEventListeners(vehicleType) |
51 | SpecializationUtil.registerEventListener(vehicleType, "onLoad", LivestockTrailer) |
52 | SpecializationUtil.registerEventListener(vehicleType, "onLoadFinished", LivestockTrailer) |
53 | SpecializationUtil.registerEventListener(vehicleType, "onReadStream", LivestockTrailer) |
54 | SpecializationUtil.registerEventListener(vehicleType, "onWriteStream", LivestockTrailer) |
55 | SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", LivestockTrailer) |
56 | SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", LivestockTrailer) |
57 | SpecializationUtil.registerEventListener(vehicleType, "onUpdate", LivestockTrailer) |
58 | end |
30 | function LivestockTrailer.registerFunctions(vehicleType) |
31 | SpecializationUtil.registerFunction(vehicleType, "addAnimal", LivestockTrailer.addAnimal) |
32 | SpecializationUtil.registerFunction(vehicleType, "addAnimals", LivestockTrailer.addAnimals) |
33 | SpecializationUtil.registerFunction(vehicleType, "removeAnimal", LivestockTrailer.removeAnimal) |
34 | SpecializationUtil.registerFunction(vehicleType, "removeAnimals", LivestockTrailer.removeAnimals) |
35 | SpecializationUtil.registerFunction(vehicleType, "getCurrentAnimalType", LivestockTrailer.getCurrentAnimalType) |
36 | SpecializationUtil.registerFunction(vehicleType, "getSupportsAnimalType", LivestockTrailer.getSupportsAnimalType) |
37 | SpecializationUtil.registerFunction(vehicleType, "getAnimals", LivestockTrailer.getAnimals) |
38 | SpecializationUtil.registerFunction(vehicleType, "getAnimalPlaces", LivestockTrailer.getAnimalPlaces) |
39 | SpecializationUtil.registerFunction(vehicleType, "setLoadingTrigger", LivestockTrailer.setLoadingTrigger) |
40 | end |
347 | function LivestockTrailer:removeAnimal(animal) |
348 | local spec = self.spec_livestockTrailer |
349 | local success = ListUtil.removeElementFromList(spec.loadedAnimals, animal) |
350 | if success then |
351 | local animalId = NetworkUtil.getObjectId(animal) |
352 | if animalId ~= nil then |
353 | spec.loadedAnimalsIds[animalId] = nil |
354 | end |
355 | |
356 | for _, slot in ipairs(spec.animalToSlots[animal]) do |
357 | delete(slot.loadedMesh) |
358 | slot.loadedMesh = nil |
359 | g_i3DManager:releaseSharedI3DFile(animal.subType.dummy.filename, nil, true) |
360 | |
361 | slot.place.numUsed = slot.place.numUsed - 1 |
362 | end |
363 | |
364 | spec.animalToSlots[animal] = nil |
365 | |
366 | self:setMassDirty() |
367 | |
368 | if self.isServer then |
369 | self:raiseDirtyFlags(spec.dirtyFlag) |
370 | end |
371 | |
372 | if #spec.loadedAnimals == 0 then |
373 | spec.currentAnimalType = nil |
374 | end |
375 | end |
376 | end |