---Specialization for automatically load objects onto a vehicle




PalletAutoLoader = {}







---
function PalletAutoLoader.prerequisitesPresent(specializations)
    return true
end

---
function PalletAutoLoader.initSpecialization()
    local schema = Vehicle.xmlSchema
    schema:setXMLSpecializationType("PalletAutoLoader")

    schema:register(XMLValueType.NODE_INDEX, "vehicle.palletAutoLoader.trigger#node", "Trigger node")
    schema:register(XMLValueType.NODE_INDEX, "vehicle.palletAutoLoader.pickupTriggers.pickupTrigger(?)#node", "Pickup trigger node")
    schema:register(XMLValueType.NODE_INDEX, "vehicle.palletAutoLoader.loadPlaces#node", "Base node of loading places definitions")
    schema:register(XMLValueType.STRING, "vehicle.palletAutoLoader#supportedObject", "Path to xml of supported object")
    schema:register(XMLValueType.INT, "vehicle.palletAutoLoader#fillUnitIndex", "Fill unit index to check fill type")
    schema:register(XMLValueType.INT, "vehicle.palletAutoLoader#maxObjects", "Max. number of objects to load", "Number of load places")
    schema:register(XMLValueType.BOOL, "vehicle.palletAutoLoader#useBales", "Use for bales", false)
    schema:register(XMLValueType.BOOL, "vehicle.palletAutoLoader#useTensionBelts", "Automatically mount tension belts", "False for mobile, otherwise true")
    schema:register(XMLValueType.VECTOR_TRANS, "vehicle.palletAutoLoader#UnloadRightOffset", "Offset for Unload right")
    schema:register(XMLValueType.VECTOR_TRANS, "vehicle.palletAutoLoader#UnloadLeftOffset", "Offset for Unload left")

    schema:setXMLSpecializationType()

    local schemaSavegame = Vehicle.xmlSchemaSavegame
    schemaSavegame:register(XMLValueType.INT, "vehicles.vehicle(?).FS22_strautmannSEK802_palletLoad.palletAutoLoader#lastUsedPalletTypeIndex", "Last used pallet type")
end

---
function PalletAutoLoader.registerFunctions(vehicleType)
    SpecializationUtil.registerFunction(vehicleType, "getIsValidObject", PalletAutoLoader.getIsValidObject)
    SpecializationUtil.registerFunction(vehicleType, "getIsAutoLoadingAllowed", PalletAutoLoader.getIsAutoLoadingAllowed)
    SpecializationUtil.registerFunction(vehicleType, "getFirstValidLoadPlace", PalletAutoLoader.getFirstValidLoadPlace)
    SpecializationUtil.registerFunction(vehicleType, "autoLoaderOverlapCallback", PalletAutoLoader.autoLoaderOverlapCallback)
    SpecializationUtil.registerFunction(vehicleType, "autoLoaderTriggerCallback", PalletAutoLoader.autoLoaderTriggerCallback)
    SpecializationUtil.registerFunction(vehicleType, "autoLoaderPickupTriggerCallback", PalletAutoLoader.autoLoaderPickupTriggerCallback)
    SpecializationUtil.registerFunction(vehicleType, "onDeletePalletAutoLoaderObject", PalletAutoLoader.onDeletePalletAutoLoaderObject)
    SpecializationUtil.registerFunction(vehicleType, "loadObject", PalletAutoLoader.loadObject)
    SpecializationUtil.registerFunction(vehicleType, "unloadAll", PalletAutoLoader.unloadAll)
end

---
function PalletAutoLoader.registerOverwrittenFunctions(vehicleType)
    SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDynamicMountTimeToMount", PalletAutoLoader.getDynamicMountTimeToMount)
end

---
function PalletAutoLoader.registerEventListeners(vehicleType)
    SpecializationUtil.registerEventListener(vehicleType, "onLoad", PalletAutoLoader)
    SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", PalletAutoLoader)
    SpecializationUtil.registerEventListener(vehicleType, "onDelete", PalletAutoLoader)
    SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", PalletAutoLoader)
	
    SpecializationUtil.registerEventListener(vehicleType, "onReadUpdateStream", PalletAutoLoader)
    SpecializationUtil.registerEventListener(vehicleType, "onWriteUpdateStream", PalletAutoLoader)
end

---
function PalletAutoLoader:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
    if self.isClient then
        local spec = self.spec_palletAutoLoader
		if spec.actionEvents == nil then
			spec.actionEvents = {}
		else
			self:clearActionEventsTable(spec.actionEvents)
		end

        if isActiveForInputIgnoreSelection then
            local state, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.ACTIVATE_OBJECT, self, PalletAutoLoader.actionEventToggleLoading, false, true, false, true, nil, nil, true, true)
            g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL)
			spec.actionEventId = actionEventId;
			
            local state, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.IMPLEMENT_EXTRA3, self, PalletAutoLoader.actionEventToggleAutoLoadTypes, false, true, false, true, nil, nil, true, true)
            g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL)
			spec.toggleAutoLoadTypesActionEventId = actionEventId;
			
            local state, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.TOGGLE_TIPSIDE, self, PalletAutoLoader.actionEventToggleTipside, false, true, false, true, nil, nil, true, true)
            g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL)
			spec.toggleTipsideActionEventId = actionEventId;
			
            local state, actionEventId = self:addActionEvent(spec.actionEvents, InputAction.UNLOAD, self, PalletAutoLoader.actionEventUnloadAll, false, true, false, true, nil, nil, true, true)
            g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL)
			spec.unloadAllEventId = actionEventId;
			
			
            PalletAutoLoader.updateActionText(self);
        end
    end
end

---
function PalletAutoLoader.updateActionText(self)
	if self.isClient then
		local spec = self.spec_palletAutoLoader
		local text;
		if spec.objectsToLoadCount == 0 then
			text = g_i18n:getText("palletAutoLoader_nothingToLoad")
		else
			text = g_i18n:getText("palletAutoLoader_loadPallets") .. ": " .. spec.objectsToLoadCount
		end
		g_inputBinding:setActionEventText(spec.actionEventId, text)
				
		local loadingText = g_i18n:getText("palletAutoLoader_LoadingType") .. ": " .. g_i18n:getText("palletAutoLoader_" .. spec.autoLoadTypes[spec.currentautoLoadTypeIndex].name)
		g_inputBinding:setActionEventText(spec.toggleAutoLoadTypesActionEventId, loadingText)
		
		local tipsideText = g_i18n:getText("palletAutoLoader_tipside") .. ": " .. g_i18n:getText("palletAutoLoader_" .. spec.currentTipside)
		g_inputBinding:setActionEventText(spec.toggleTipsideActionEventId, tipsideText)
		
		-- deactivate when somthing is already loaded or not
		g_inputBinding:setActionEventActive(spec.toggleAutoLoadTypesActionEventId, spec.numTriggeredObjects == 0)
		g_inputBinding:setActionEventActive(spec.unloadAllEventId, spec.numTriggeredObjects ~= 0)
	end
end

---
function PalletAutoLoader.actionEventToggleLoading(self, actionName, inputValue, callbackState, isAnalog)
    local spec = self.spec_palletAutoLoader
	
	if not self.isServer then
		-- Ladebefehl in den stream schreiben
		spec.LoadNextObject = true;
		self:raiseDirtyFlags(spec.dirtyFlag)
	else
		for _, object in pairs(spec.objectsToLoad) do
		
			local isValidLoadType = spec.autoLoadTypes[spec.currentautoLoadTypeIndex].CheckTypeMethod(object);
			if isValidLoadType then
				self:loadObject(object);
				break;
			end
		end
		PalletAutoLoader.updateActionText(self);
	end
end

---
function PalletAutoLoader.actionEventToggleAutoLoadTypes(self, actionName, inputValue, callbackState, isAnalog)
    local spec = self.spec_palletAutoLoader
	
	if spec.currentautoLoadTypeIndex >= #spec.autoLoadTypes then
		spec.currentautoLoadTypeIndex = 1;
	else
		spec.currentautoLoadTypeIndex = spec.currentautoLoadTypeIndex + 1;
	end
	self:raiseDirtyFlags(spec.dirtyFlag)
	PalletAutoLoader.updateActionText(self);
end

---
function PalletAutoLoader.actionEventToggleTipside(self, actionName, inputValue, callbackState, isAnalog)
    local spec = self.spec_palletAutoLoader
	
	if spec.currentTipside == "left" then
		spec.currentTipside = "right";
	else
		spec.currentTipside = "left";
	end
	self:raiseDirtyFlags(spec.dirtyFlag)
	PalletAutoLoader.updateActionText(self);
end

---
function PalletAutoLoader.actionEventUnloadAll(self, actionName, inputValue, callbackState, isAnalog)
    local spec = self.spec_palletAutoLoader
	
	if not self.isServer then
		-- Entladebefehl in den stream schreiben mit entladeseite
		spec.callUnloadAll = true;
		self:raiseDirtyFlags(spec.dirtyFlag)
	else
		self:unloadAll()
		PalletAutoLoader.updateActionText(self);
	end
end

---Called on loading
-- @param table savegame savegame
function PalletAutoLoader:onLoad(savegame)

	-- hier für server und client
	self.spec_palletAutoLoader = {}
	local spec = self.spec_palletAutoLoader
	spec.LoadNextObject = false;
	spec.callUnloadAll = true;
	spec.objectsToLoadCount = 0;	
	spec.dirtyFlag = self:getNextDirtyFlag()
    spec.numTriggeredObjects = 0
	spec.currentTipside = "left";
		
	local loadPlacesNode = self.xmlFile:getValue("vehicle.palletAutoLoader.loadPlaces#node", nil, self.components, self.i3dMappings)
	local numOfTypes = getNumOfChildren(loadPlacesNode)
	if numOfTypes > 0 then
		spec.autoLoadTypes = {}
		spec.currentautoLoadTypeIndex = 1;
		for typeIndex = 0, (numOfTypes-1) do
			local autoLoadObject = {}
			local typeNodeId = getChildAt(loadPlacesNode, typeIndex)
			local name = getName(typeNodeId)
			autoLoadObject.index = typeNodeId
			autoLoadObject.name = name
			PalletAutoLoader:AddSupportedObjects(autoLoadObject, name)
			autoLoadObject.places = {}
			
			local numOfPlaces = getNumOfChildren(typeNodeId)
			for placeIndex = 0, (numOfPlaces-1) do
				local place = {}
				place.node = getChildAt(typeNodeId, placeIndex)
				table.insert(autoLoadObject.places, place)
			end
			
			table.insert(spec.autoLoadTypes, autoLoadObject)
		end
	end	
	
    if self.isServer then
		spec.objectsToLoad = {};

        spec.triggerId = self.xmlFile:getValue("vehicle.palletAutoLoader.trigger#node", nil, self.components, self.i3dMappings)
        if spec.triggerId ~= nil then
            addTrigger(spec.triggerId, "autoLoaderTriggerCallback", self);
        end
		
        spec.pickupTriggers = {}
		
        local i = 0
        while true do
            local pickupTriggerKey = string.format("vehicle.palletAutoLoader.pickupTriggers.pickupTrigger(%d)", i)
            if not self.xmlFile:hasProperty(pickupTriggerKey) then
                break
            end

            local entry = {}
            entry.node = self.xmlFile:getValue(pickupTriggerKey .. "#node", nil, self.components, self.i3dMappings)

            if entry.node ~= nil then
                table.insert(spec.pickupTriggers, entry)
				addTrigger(entry.node, "autoLoaderPickupTriggerCallback", self)
            end

            i = i + 1
        end

        spec.triggeredObjects = {}
		
        spec.supportedObject = self.xmlFile:getValue("vehicle.palletAutoLoader#supportedObject")

        spec.fillUnitIndex = self.xmlFile:getValue("vehicle.palletAutoLoader#fillUnitIndex")
        spec.maxObjects = self.xmlFile:getValue("vehicle.palletAutoLoader#maxObjects") or #spec.loadPlaces
        spec.useBales = self.xmlFile:getValue("vehicle.palletAutoLoader#useBales", false)
        spec.useTensionBelts = self.xmlFile:getValue("vehicle.palletAutoLoader#useTensionBelts", not GS_IS_MOBILE_VERSION)
		spec.UnloadOffset = {}
        spec.UnloadOffset["right"] = self.xmlFile:getValue("vehicle.palletAutoLoader#UnloadRightOffset", "-3 -0.5 0", true)
        spec.UnloadOffset["left"] = self.xmlFile:getValue("vehicle.palletAutoLoader#UnloadLeftOffset", "3 -0.5 0", true)
		
		-- missing in xml
		spec.maxLoadHeight = 2;
    end
	
    spec.initialized = true;
end

---Called after loading
-- @param table savegame savegame
function PalletAutoLoader:onPostLoad(savegame)
    if savegame ~= nil then
		local spec = self.spec_palletAutoLoader

        if not savegame.resetVehicles then
            spec.currentautoLoadTypeIndex = savegame.xmlFile:getValue(savegame.key..".FS22_strautmannSEK802_palletLoad.palletAutoLoader#lastUsedPalletTypeIndex", 1)
        end
	end
end

---
function PalletAutoLoader:saveToXMLFile(xmlFile, key, usedModNames)
    local spec = self.spec_palletAutoLoader

	xmlFile:setValue(key.."#lastUsedPalletTypeIndex", spec.currentautoLoadTypeIndex)
end

---
function PalletAutoLoader:AddSupportedObjects(autoLoadObject, name)
	if (name == "euroPallet") then
		local function CheckType(object)
			if object.configFileName == "data/objects/pallets/pioneer/pioneerPallet.xml" then return true end
			if object.configFileName == "data/objects/pallets/grapePallet/grapePallet.xml" then return true end
			
			for mappingName, _ in pairs(object.i3dMappings) do
				if (mappingName == "euroPalletVis") then
				return true;
				end
			end
			
			return false;
		end	
	
		autoLoadObject.CheckTypeMethod = CheckType
		autoLoadObject.sizeX = 1.2
		autoLoadObject.sizeY = 1
		autoLoadObject.sizeZ = 0.8
	elseif (name == "liquidTank") then
		local function CheckType(object)
			if string.find(object.i3dFilename, "data/objects/pallets/liquidTank") then
				return true;
			end
			return false;
		end	
	
		autoLoadObject.CheckTypeMethod = CheckType
		autoLoadObject.sizeX = 1.5
		autoLoadObject.sizeY = 2
		autoLoadObject.sizeZ = 1.5
	elseif (name == "bigBagPallet") then
		local function CheckType(object)
			for mappingName, _ in pairs(object.i3dMappings) do
				if (mappingName == "bigBagPallet_vis") then
				return true;
				end
			end
			return false;
		end	
	
		autoLoadObject.CheckTypeMethod = CheckType
		autoLoadObject.sizeX = 1.4
		autoLoadObject.sizeY = 2
		autoLoadObject.sizeZ = 1.2
	end
end

---
function PalletAutoLoader:onDelete()
    local spec = self.spec_palletAutoLoader

    if self.isServer then
        if spec.triggerId ~= nil then
            removeTrigger(spec.triggerId)
        end

        if spec.pickupTriggers ~= nil then
			for _, pickupTrigger in pairs(spec.pickupTriggers) do
				removeTrigger(pickupTrigger.node)
			end            
        end
    end
end

---
function PalletAutoLoader:getIsValidObject(object)
    local spec = self.spec_palletAutoLoader
			
	-- only when rootnode is object id it can be valid.
	if object.spec_mountable == nil or object.spec_mountable.componentNode ~= object.rootNode then
		return false;
	end
	
	local objectFilename = object.configFileName or object.i3dFilename
	if objectFilename ~= nil then
		-- if not string.find(objectFilename, spec.supportedObject) then
		if object.typeName ~= "pallet" then
			return false
		end
	else
		return false
	end

    if object == self then
        return false
    end

    if spec.useBales and (not object:isa(Bale) or not object:getAllowPickup()) then
        return false
    end

    if not g_currentMission.accessHandler:canFarmAccess(self:getActiveFarm(), object) then
        return false
    end

    if spec.fillUnitIndex ~= nil and object.getFillType ~= nil and not self:getFillUnitSupportsFillType(spec.fillUnitIndex, object:getFillType()) then
        return false
    end

    return true
end

---
function PalletAutoLoader:getIsAutoLoadingAllowed()
    -- check if the vehicle has not fallen to side
    local _, y1, _ = getWorldTranslation(self.components[1].node)
    local _, y2, _ = localToWorld(self.components[1].node, 0, 1, 0)
    if y2 - y1 < 0.5 then
        return false
    end

    return true
end

---
function PalletAutoLoader:getDynamicMountTimeToMount(superFunc)
	return self:getIsAutoLoadingAllowed() and -1 or math.huge
end

---
function PalletAutoLoader:getFirstValidLoadPlace()
    local spec = self.spec_palletAutoLoader

	-- Hier die loading position und das loading objekt nehmen und die erste ladeposition dafür dynamisch suchen
	-- https://gdn.giants-software.com/documentation_scripting_fs19.php?version=engine&category=15&function=138
	-- overlapBox scheint zu prüfen, ob der angegebene Bereich frei ist
	
	local currentLoadHeigt = 0;
	local autoLoadType = spec.autoLoadTypes[spec.currentautoLoadTypeIndex];
	local loadPlaces = spec.autoLoadTypes[spec.currentautoLoadTypeIndex].places;
	while currentLoadHeigt  <= spec.maxLoadHeight do
	
		for i=1, #loadPlaces do
			local loadPlace = loadPlaces[i]
			local x, y, z = localToWorld(loadPlace.node, 0, currentLoadHeigt, 0);
			local rx, ry, rz = getWorldRotation(loadPlace.node)
			
			-- collision mask : all bits except bit 13, 23, 30
			spec.foundObject = false 
			overlapBox(x, y + (autoLoadType.sizeY / 2), z, rx, ry, rz, autoLoadType.sizeX / 2, autoLoadType.sizeY / 2, autoLoadType.sizeZ / 2, "autoLoaderOverlapCallback", self, 3212828671, true, false, true)

			if not spec.foundObject then
				return i, currentLoadHeigt
			end
		end
		
		currentLoadHeigt = currentLoadHeigt + 0.1
	end

    return -1, 0
end

---
function PalletAutoLoader:autoLoaderOverlapCallback(transformId)
    if transformId ~= 0 and getHasClassId(transformId, ClassIds.SHAPE) then
        local spec = self.spec_palletAutoLoader

        local object = g_currentMission:getNodeObject(transformId)
        if object ~= nil and object ~= self then
            spec.foundObject = true
        end
    end

    return true
end

---
function PalletAutoLoader:loadObject(object)
	if object ~= nil then
		if self:getIsAutoLoadingAllowed() and self:getIsValidObject(object) then
			local spec = self.spec_palletAutoLoader
			if spec.triggeredObjects[object] == nil then
				if spec.numTriggeredObjects < spec.maxObjects then
					local firstValidLoadPlace, currentLoadHeigt = self:getFirstValidLoadPlace()
					if firstValidLoadPlace ~= -1 then
						local loadPlaces = spec.autoLoadTypes[spec.currentautoLoadTypeIndex].places;
						local loadPlace = loadPlaces[firstValidLoadPlace]
						local x,y,z = localToWorld(loadPlace.node, 0, currentLoadHeigt, 0);
						local objectNodeId = object.nodeId or object.components[1].node

						removeFromPhysics(objectNodeId)

						setWorldRotation(objectNodeId, getWorldRotation(loadPlace.node))
						setTranslation(objectNodeId, x, y, z)

						addToPhysics(objectNodeId)

						local vx, vy, vz = getLinearVelocity(self:getParentComponent(loadPlace.node))
						if vx ~= nil then
							setLinearVelocity(objectNodeId, vx, vy, vz)
						end
						
						spec.triggeredObjects[object] = 0
						spec.numTriggeredObjects = spec.numTriggeredObjects + 1

						if spec.useTensionBelts and self.setAllTensionBeltsActive ~= nil then
							self:setAllTensionBeltsActive(false, false)
							--- PAUSE !!!
							
							self:setAllTensionBeltsActive(true, false)
						end
						
						if spec.objectsToLoad[object.rootNode] ~= nil then
							spec.objectsToLoad[object.rootNode] = nil;
							spec.objectsToLoadCount = spec.objectsToLoadCount - 1;
						end
						self:raiseDirtyFlags(spec.dirtyFlag)
					end
				end
			end
		end
	end
end

---
function PalletAutoLoader:unloadAll()
	local spec = self.spec_palletAutoLoader

	for object,_ in pairs(spec.triggeredObjects) do
		if object ~= nil then
			local objectNodeId = object.nodeId or object.components[1].node
			
			-- store current rotation to restore later
			local rx,ry,rz = getWorldRotation(objectNodeId); 
			
			-- set rotation to trailer rotation to move to a side
			setWorldRotation(objectNodeId, getWorldRotation(self.rootNode))
			
			--local x,y,z = localToWorld(objectNodeId, -3, -0.5, 0);
			local x,y,z = localToWorld(objectNodeId, unpack(spec.UnloadOffset[spec.currentTipside]));

			-- move object and restore rotation
			removeFromPhysics(objectNodeId)
			setWorldRotation(objectNodeId, rx,ry,rz)
			setTranslation(objectNodeId, x, y, z)
			addToPhysics(objectNodeId)
			
			if object.addDeleteListener ~= nil then
				object:addDeleteListener(self, "onDeletePalletAutoLoaderObject")
			end
		end
	end
	spec.triggeredObjects = {}
	spec.numTriggeredObjects = 0
	self:raiseDirtyFlags(spec.dirtyFlag)

end


---Called on on update
-- @param integer streamId stream ID
-- @param integer timestamp timestamp
-- @param table connection connection
function PalletAutoLoader:onReadUpdateStream(streamId, timestamp, connection)
    local spec = self.spec_palletAutoLoader

    if not connection:getIsServer() then
		-- print("Received from Client");
		local LoadNextObject = streamReadBool(streamId);
		spec.currentautoLoadTypeIndex = streamReadInt32(streamId);
		spec.currentTipside = streamReadString(streamId);
		local callUnloadAll = streamReadBool(streamId);
		
		if LoadNextObject then
			-- Load like on non dedi serverside
			for _, object in pairs(spec.objectsToLoad) do
				local isValidLoadType = spec.autoLoadTypes[spec.currentautoLoadTypeIndex].CheckTypeMethod(object);
				if isValidLoadType then
					self:loadObject(object);
					break;
				end
			end
		end
		
		if callUnloadAll then
			self:unloadAll()
		end
	else
		-- print("Received from Server");
		local numTriggeredObjects = streamReadInt32(streamId);
		if spec.numTriggeredObjects ~= numTriggeredObjects then
			spec.numTriggeredObjects = numTriggeredObjects;
			PalletAutoLoader.updateActionText(self);
		end
		local objectsToLoadCount = streamReadInt32(streamId);
		if spec.objectsToLoadCount ~= objectsToLoadCount then
			spec.objectsToLoadCount = objectsToLoadCount;
			PalletAutoLoader.updateActionText(self);
		end
    end
end


---Called on on update
-- @param integer streamId stream ID
-- @param table connection connection
-- @param integer dirtyMask dirty mask
function PalletAutoLoader:onWriteUpdateStream(streamId, connection, dirtyMask)
    local spec = self.spec_palletAutoLoader

    if connection:getIsServer() then
		-- print("Send to Server");
		streamWriteBool(streamId, spec.LoadNextObject)
		streamWriteInt32(streamId, spec.currentautoLoadTypeIndex)
		streamWriteString(streamId, spec.currentTipside)
		streamWriteBool(streamId, spec.callUnloadAll)
		
		-- zurücksetzen
		spec.LoadNextObject = false;
		spec.callUnloadAll = false;
	else
		-- print("Send to Client");
		streamWriteInt32(streamId, spec.numTriggeredObjects);
		streamWriteInt32(streamId, spec.objectsToLoadCount);
    end
end

---
function PalletAutoLoader:autoLoaderPickupTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
	if otherActorId ~= 0 then
		local object = g_currentMission:getNodeObject(otherActorId)
		if object ~= nil then
			if self:getIsAutoLoadingAllowed() and self:getIsValidObject(object) then
				local spec = self.spec_palletAutoLoader
				if onEnter then
					if spec.objectsToLoad[object.rootNode] == nil and spec.triggeredObjects[object] == nil then
						spec.objectsToLoad[object.rootNode] = object;
						spec.objectsToLoadCount = spec.objectsToLoadCount + 1;
						self:raiseDirtyFlags(spec.dirtyFlag)
						PalletAutoLoader.updateActionText(self);
					end
				elseif onLeave then
					if spec.objectsToLoad[object.rootNode] ~= nil then
						spec.objectsToLoad[object.rootNode] = nil;
						spec.objectsToLoadCount = spec.objectsToLoadCount - 1;
						self:raiseDirtyFlags(spec.dirtyFlag)
						PalletAutoLoader.updateActionText(self);
					end
				end
			end
		end
    end
end


--DebugUtil.printTableRecursively(object,"_",0,2)
--print(string.format("Geometry ID: %d", getGeometry(triggerId)));
-- local targetArea = g_currentMission:getNodeObject(triggerId)
-- if targetArea == nil then
-- targetArea = g_currentMission.nodeToObject[triggerId]
-- end
-- DebugUtil.printTableRecursively(targetArea,"_",0,2)

---
function PalletAutoLoader:autoLoaderTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
    local spec = self.spec_palletAutoLoader

    if onEnter then
        local object = g_currentMission:getNodeObject(otherActorId)
        if object ~= nil then
            if self:getIsValidObject(object) then
                if spec.triggeredObjects[object] == nil then
                    spec.triggeredObjects[object] = 0
                    spec.numTriggeredObjects = spec.numTriggeredObjects + 1
                end

                if spec.triggeredObjects[object] == 0 then
                    if object.addDeleteListener ~= nil then
                        object:addDeleteListener(self, "onDeletePalletAutoLoaderObject")
                    end
                end

                spec.triggeredObjects[object] = spec.triggeredObjects[object] + 1
				self:raiseDirtyFlags(spec.dirtyFlag)
            end
        end
    elseif onLeave then
        local object = g_currentMission:getNodeObject(otherActorId)
        if object ~= nil then
            if self:getIsValidObject(object) then
                if spec.triggeredObjects[object] ~= nil then
                    spec.triggeredObjects[object] = spec.triggeredObjects[object] - 1

                    if spec.triggeredObjects[object] == 0 then
                        spec.triggeredObjects[object] = nil
                        spec.numTriggeredObjects = spec.numTriggeredObjects - 1

                        if object.removeDeleteListener ~= nil then
                            object:removeDeleteListener(self)
                        end
						self:raiseDirtyFlags(spec.dirtyFlag)
                    end

                    if next(spec.triggeredObjects) == nil then
                        spec.currentPlace = 1
                    end
                end
            end
        end
    end
end

---
function PalletAutoLoader:onDeletePalletAutoLoaderObject(object)
    local spec = self.spec_palletAutoLoader

    if spec.triggeredObjects[object] ~= nil then
        spec.triggeredObjects[object] = nil
        spec.numTriggeredObjects = spec.numTriggeredObjects - 1

        if next(spec.triggeredObjects) == nil then
            spec.currentPlace = 1
        end
    end
end
