--
-- ALW for FS19
-- @author:    	Marhu, kenny456 - FS19 conversion (kenny456@seznam.cz)
-- @history:	v1.0 - 2018-12-25 - converted to FS19
--								  - added function to move loading position FWD/BWD depending on logs length
--				v1.1 - 2018-12-28 - fixed multiplayer errors on dedi server
--				v1.2 - 2018-03-09 - -added new 15m and 20m trailers
--									-fixed showing controls when attached to dolly
--									-Autoload script edited (logs are now sorted to the piles)
--
ALW = {};
ALW.confDir = getUserProfileAppPath().. "modsSettings/ALW/";
local modName = g_currentModName

function ALW:getTexts(i,text)
	if g_currentMission.ALW == nil then
		g_currentMission.ALW = {}
		g_currentMission.ALW.texts = {}
	end
	g_currentMission.ALW.texts[i] = text
end

function ALW.prerequisitesPresent(specializations)
    return true
end

function ALW.initSpecialization()
end

function ALW.registerOverwrittenFunctions(vehicleType)
	SpecializationUtil.registerOverwrittenFunction(vehicleType, "dynamicMountTriggerCallback", ALW.dynamicMountTriggerCallback)
end

function ALW.registerFunctions(vehicleType)
	SpecializationUtil.registerFunction(vehicleType, "toggleState", ALW.toggleState)
	SpecializationUtil.registerFunction(vehicleType, "toggleLoad", ALW.toggleLoad)
	SpecializationUtil.registerFunction(vehicleType, "toggleUnload", ALW.toggleUnload)
	SpecializationUtil.registerFunction(vehicleType, "updateValues", ALW.updateValues)
	SpecializationUtil.registerFunction(vehicleType, "updateLoad", ALW.updateLoad)
	SpecializationUtil.registerFunction(vehicleType, "updateUnload", ALW.updateUnload)
	SpecializationUtil.registerFunction(vehicleType, "getIsTurnedOn", ALW.getIsTurnedOn)
	SpecializationUtil.registerFunction(vehicleType, "saveToXml", ALW.saveToXml)
	SpecializationUtil.registerFunction(vehicleType, "loadFromXml", ALW.loadFromXml)
end

function ALW.registerEvents(vehicleType)
end

function ALW:registerActionEventsPlayer()
end

function ALW:registerActionEventsMenu()
end
function ALW:onRegisterActionEvents(isSelected, isOnActiveVehicle)
	local spec = self.spec_ALW
	if g_dedicatedServerInfo ~= nil then
		return
	end
	if spec.event_IDs == nil then
		spec.event_IDs = {}
	end
	if isSelected then
		local actions_RC1 = { InputAction.ALW_TOGGLE_AUTO, InputAction.ALW_TOGGLE_UNLOAD, InputAction.ALW_TOGGLE_SIDE, InputAction.ALW_TOGGLE_SHOW_POSITION,
							InputAction.ALW_TOGGLE_PILES, InputAction.ALW_SWITCH_PILE, InputAction.ALW_TOGGLE_LOAD_MARKER, InputAction.ALW_TOGGLE_UNLOAD_MARKER,
							InputAction.ALW_UNLOAD_MARKER_MOVE, InputAction.ALW_UNLOAD_MARKER_SCALE, InputAction.ALW_UNLOAD_MARKER_ROTATE, InputAction.ALW_TOGGLE_HELP}

		for _,actionName in pairs(actions_RC1) do
			local _, eventID = g_inputBinding:registerActionEvent(actionName, self, ALW.actionCallback, true, true, false, true)
			spec.event_IDs[actionName] = eventID
			if g_inputBinding ~= nil and g_inputBinding.events ~= nil and g_inputBinding.events[eventID] ~= nil then
				if actionName == InputAction.ALW_TOGGLE_AUTO or actionName == InputAction.ALW_TOGGLE_UNLOAD or actionName == InputAction.ALW_TOGGLE_SIDE then
					g_inputBinding.events[eventID].displayPriority = 1
				else
					g_inputBinding.events[eventID].displayPriority = 2
				end
				if actionName == InputAction.ALW_TOGGLE_HELP then
					g_inputBinding:setActionEventTextVisibility(eventID, true)
				elseif actionName == InputAction.RC_TOGGLE or actionName == InputAction.RC_TOGGLE_ALL then
					g_inputBinding:setActionEventTextVisibility(eventID, false)
				else
					g_inputBinding:setActionEventTextVisibility(eventID, ALW.showHelp)
				end
				if actionName == InputAction.ALW_TOGGLE_SHOW_POSITION then
					g_inputBinding:setActionEventActive(eventID, false)
				end
			end
		end
	end
end

function ALW.registerEventListeners(vehicleType)
	for _,n in pairs( { "onLoad","onPostLoad","saveToXMLFile","onUpdate","onDraw","onRegisterActionEvents","registerActionEventsPlayer","saveToXml","loadFromXml","onReadStream","onWriteStream" } ) do
		SpecializationUtil.registerEventListener(vehicleType, n, ALW)
	end
end

function ALW:onLoad(savegame)
	self.spec_ALW = {}
	local spec = self.spec_ALW
	local xmlFile = self.xmlFile
	spec.event_IDs = {}
	
	spec.searchSizeY = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.ALW#SizeY"),5);
	spec.searchSizeZ = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.ALW#SizeX"),10);
	spec.autoLoadSpeed = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.ALW#Speed"),500);
	spec.autoLoadElaps = 0;
	spec.dynamicMountTrigger = I3DUtil.indexToObject(self.components, self.i3dMappings.dynamicMountTrigger);
	spec.ALW = I3DUtil.indexToObject(self.components, self.i3dMappings.ALW);
	spec.ALWBegin = I3DUtil.indexToObject(self.components, self.i3dMappings.ALWBegin);
	
	local x,y,z = getTranslation(spec.dynamicMountTrigger)
	local key = "vehicle.ALW.fillPose";
	local fillPoseXOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#xOff"),0);
	local fillPoseYOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#yOff"),2);
	local fillPoseZOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#zOff"),0);
	
	local key = "vehicle.ALW.unloadPose";
	local unloadPoseXOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#xOff"),0);
	local unloadPoseYOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#yOff"),5);
	local unloadPoseZOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#zOff"),0);
		
	spec.fillPoseNodeX = x + fillPoseXOff
	spec.fillPoseNodeY = 1.4 + fillPoseYOff
	spec.fillPoseNodeZ = z + fillPoseZOff
	spec.fillPoseRoot = createTransformGroup("fillPoseRoot");
	spec.fillPoseNode = createTransformGroup("fillPoseNode");
	link(spec.ALW,spec.fillPoseRoot);
	link(spec.fillPoseRoot,spec.fillPoseNode);
	setTranslation(spec.fillPoseRoot, spec.fillPoseNodeX, spec.fillPoseNodeY, spec.fillPoseNodeZ)
	setRotation(spec.fillPoseRoot,math.rad(-90),0,0)
	
	local linkNode = getParent(getParent(spec.dynamicMountTrigger))
	spec.unloadPoseRoot = {	createTransformGroup("unloadPoseRoot1"),
							createTransformGroup("unloadPoseRoot2")};
	spec.unloadPoseNode = {	createTransformGroup("unloadPoseNode1"),
								createTransformGroup("unloadPoseNode2")};
	spec.unloadPoseRootX = 2
	spec.unloadPoseRootY = 0
	spec.unloadPoseRootZ = 0
	for i = 1, 2 do
		link(linkNode, spec.unloadPoseRoot[i]);
		setTranslation(spec.unloadPoseRoot[i],spec.unloadPoseRootX,spec.unloadPoseRootY,spec.unloadPoseRootZ)
		setRotation(spec.unloadPoseRoot[i],math.rad(0),math.rad(0),0)
		spec.unloadPoseRootX = spec.unloadPoseRootX * -1;
	end
	
	spec.unloadPoseNodeX =  unloadPoseXOff
	spec.unloadPoseNodeY  = unloadPoseYOff
	spec.unloadPoseNodeZ  = unloadPoseZOff
	for i = 1, 2 do					
		link(spec.unloadPoseRoot[i], spec.unloadPoseNode[i]);
		setTranslation(spec.unloadPoseNode[i], spec.unloadPoseNodeX, spec.unloadPoseNodeY, spec.unloadPoseNodeZ)
		setRotation(spec.unloadPoseNode[i],math.rad(-90),0,0)
		spec.unloadPoseNodeX = spec.unloadPoseNodeX * -1;
	end
		
	spec.loadMarker = I3DUtil.indexToObject(self.components, self.i3dMappings['loadMarker'])
	spec.unloadMarker = I3DUtil.indexToObject(self.components, self.i3dMappings['unloadMarker'])
	if spec.loadMarker ~= nil then
		spec.markerX, spec.markerY, spec.markerZ = getTranslation(spec.loadMarker)
		setVisibility(spec.loadMarker, false);
		link(spec.fillPoseRoot, spec.loadMarker);
		setRotation(spec.loadMarker,math.rad(90),0,math.rad(90))
		setTranslation(spec.loadMarker,0,0,-3.1)
	end
	if spec.unloadMarker ~= nil then
		spec.markerX, spec.markerY, spec.markerZ = getTranslation(spec.unloadMarker)
		setVisibility(spec.unloadMarker, false);
		link(spec.unloadPoseRoot[1], spec.unloadMarker);
	end
	
	if self.isServer then
		local key = "vehicle.ALW.woodTrigger";
		local woodTriggerXOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#xOff"),1.2);
		local woodTriggerYOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#yOff"),-3);
		local woodTriggerZOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#zOff"),1.5);

		local key = "vehicle.ALW.limitToLen";
		spec.loadMinLen = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#minLen"),2.5);
		spec.loadMaxLen = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#maxLen"),20);
		spec.loadMaxAtt = Utils.getNoNil(getXMLInt(xmlFile, key .. "#delimbOk"),0);
		
		local linkNode = getParent(spec.dynamicMountTrigger)
		local x,y,z = getTranslation(spec.dynamicMountTrigger)
		
		spec.woodTrigger = {createTransformGroup("woodTrigger1"),
							createTransformGroup("woodTrigger2"),
							createTransformGroup("woodTrigger3"),
							createTransformGroup("woodTrigger4")};
		
		local rot = math.rad(90)
		for i = 1, 4 do					
			link(linkNode, spec.woodTrigger[i]);
			setTranslation(spec.woodTrigger[i], x + woodTriggerXOff, y + woodTriggerYOff, z + woodTriggerZOff)
			setRotation(spec.woodTrigger[i], 0, rot, 0);
			woodTriggerZOff = woodTriggerZOff * -1;
			if i == 2 then 
				woodTriggerXOff = woodTriggerXOff * -1;
				rot = math.rad(-90)
			end
		end
	end;
end
function ALW:onPostLoad(savegame)
	local spec = self.spec_ALW
	local xmlFile = self.xmlFile
	if spec.event_IDs == nil then
		spec.event_IDs = {}
	end
	spec.woodLoad = {};
	spec.autoload = false;
	spec.rightSide = false;
	spec.unload = false;
	spec.showLoadPos = false;
	spec.numPiles = 2;
	spec.pile = 1;
	spec.showPosition = false;
	spec.showUnloadPos = false;
	spec.unloadPos = spec.unloadPoseRootX
	spec.unloadScale = 1;
	spec.unloadRot = false;
	spec.trailer = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.base.size#length"),15);
	spec.space = 0.2
	spec.rootShiftRotX = 6;
	spec.rootShiftRotXMax = 9;
	ALW.showHelp = true
	
	self:updateValues()
	self:updateLoad()
	self:updateUnload()
	
	if savegame ~= nil then
		local xmlFile = savegame.xmlFile
		local key = savegame.key.."."..modName..".ALW12"
		local rightSide = Utils.getNoNil(getXMLBool(xmlFile, key.."#rightSide"), spec.rightSide);
		local showLoadPos = Utils.getNoNil(getXMLBool(xmlFile, key.."#showLoadPos"), spec.showLoadPos);
		local showUnloadPos = Utils.getNoNil(getXMLBool(xmlFile, key.."#showUnloadPos"), spec.showUnloadPos);
		local numPiles = Utils.getNoNil(getXMLInt(xmlFile, key.."#numPiles"), spec.numPiles);
		local pile = Utils.getNoNil(getXMLInt(xmlFile, key.."#pile"), spec.pile);
		local unloadPos = Utils.getNoNil(getXMLFloat(xmlFile, key.."#unloadPos"), spec.unloadPos);
		local unloadScale = Utils.getNoNil(getXMLFloat(xmlFile, key.."#unloadScale"), spec.unloadScale);
		local unloadRot = Utils.getNoNil(getXMLBool(xmlFile, key.."#unloadRot"), spec.unloadRot);
		local showPosition = Utils.getNoNil(getXMLBool(xmlFile, key.."#showPosition"), spec.showPosition);
		
		self:toggleState(autoload, rightSide, unload, true)
		self:toggleLoad(showLoadPos, numPiles, pile, showPosition, true)
		self:toggleUnload(showUnloadPos, unloadPos, unloadScale, unloadRot, true)
	end
	
	local configFile = ALW.confDir .. "ALWConfig.xml";
	if fileExists(configFile) then
		ALW.configXml = loadXMLFile("ALW_XML", configFile);
		self:loadFromXml(self:getFullName());
	else
		createFolder(getUserProfileAppPath().. "modsSettings/");
		createFolder(ALW.confDir);
		ALW.configXml = createXMLFile("ALW_XML", configFile, "ALWConfig");
		self:saveToXml();
		saveXMLFile(ALW.configXml);
	end
end
function ALW:saveToXMLFile(xmlFile, key)
	local spec = self.spec_ALW
	
	setXMLBool(xmlFile, key.."#rightSide", spec.rightSide)
	setXMLBool(xmlFile, key.."#showLoadPos", spec.showLoadPos)
	setXMLBool(xmlFile, key.."#showUnloadPos", spec.showUnloadPos)
	setXMLInt(xmlFile, key.."#numPiles", spec.numPiles)
	setXMLInt(xmlFile, key.."#pile", spec.pile)
	setXMLFloat(xmlFile, key.."#unloadPos", spec.unloadPos)
	setXMLFloat(xmlFile, key.."#unloadScale", spec.unloadScale)
	setXMLBool(xmlFile, key.."#unloadRot", spec.unloadRot)
	setXMLBool(xmlFile, key.."#showPosition", spec.showPosition)
end

function ALW:loadFromXml()
	local spec = self.spec_ALW
    if ALW.configXml == nil then
        return;
    end
	if getXMLBool(ALW.configXml, "ALWConfig.showHelp") ~= nil then
		ALW.showHelp = getXMLBool(ALW.configXml, "ALWConfig.showHelp")
	end;
end
function ALW:saveToXml()
	local spec = self.spec_ALW
    if ALW.configXml == nil then
        return;
    end
	setXMLBool(ALW.configXml, "ALWConfig.showHelp", ALW.showHelp);
    saveXMLFile(ALW.configXml);
end
function ALW:onUpdate(dt, vehicle)
	local spec = self.spec_ALW
	
	if spec.autoload then
		spec.autoLoadElaps = spec.autoLoadElaps + dt;
		if spec.autoLoadElaps >= spec.autoLoadSpeed then
			spec.autoLoadElaps = 0;
			if self.isServer then
				if entityExists(spec.lastWoodShapes) and spec.woodLoad[spec.lastWoodShapes] == nil then
					if spec.pile + 1 <= spec.numPiles then
						spec.pile = spec.pile + 1
						spec.lastWoodShapes = 0
						self:toggleLoad(spec.showLoadPos, spec.numPiles, spec.pile, spec.showPosition)
					else
						self:toggleState(false, spec.rightSide, spec.unload, spec.showPosition)
						return;
					end
				end;
				
				local triggerNum = (spec.rightSide and 2 or 0) + 1;
				
				local x,y,z = getWorldTranslation(spec.woodTrigger[triggerNum])
				local nx, ny, nz = localDirectionToWorld(spec.woodTrigger[triggerNum], 1, 0, 0)
				local yx, yy, yz = localDirectionToWorld(spec.woodTrigger[triggerNum], 0, 1, 0)
				local shape, minY, maxY, minZ, maxZ = findSplitShape(x, y, z, nx, ny, nz, yx, yy, yz, spec.searchSizeY, spec.searchSizeZ)
				
				if shape == nil or not entityExists(shape) or getRigidBodyType(shape) ~= "Dynamic" or spec.badTree == shape then
					triggerNum = triggerNum + 1;
					x,y,z = getWorldTranslation(spec.woodTrigger[triggerNum])
					nx, ny, nz = localDirectionToWorld(spec.woodTrigger[triggerNum], 1, 0, 0)
					yx, yy, yz = localDirectionToWorld(spec.woodTrigger[triggerNum], 0, 1, 0)
					shape, minY, maxY, minZ, maxZ = findSplitShape(x, y, z, nx, ny, nz, yx, yy, yz, spec.searchSizeY, spec.searchSizeZ)
				end	
				local fX,fY,fZ = getTranslation(spec.fillPoseNode)
				if fX < 0.5 then
					fX = fX + 0.5;
				else
					fX = -0.8;
						rotate(spec.fillPoseNode, 0,0, math.rad(180))
						spec.fXRot = not spec.fXRot
				end
				setTranslation(spec.fillPoseNode, fX, fY, fZ)
				if shape ~= nil and entityExists(shape) and getRigidBodyType(shape) == "Dynamic" then
					
					local sizeX, sizeY, sizeZ, numConvexes, numAttachments = getSplitShapeStats(shape)
					local maxSize = math.max(sizeX, math.max(sizeY, sizeZ)) --fcelsa
					local a, b, c = localToWorld(spec.woodTrigger[triggerNum], 0, (minY + maxY)*0.5, (minZ + maxZ)*0.5)
					local sx,sy,sz = getWorldTranslation(shape)
					local dist = MathUtil.vector3Length(a - sx, b - sy, c - sz)
					local nx, ny, nz = localDirectionToWorld(shape, 0, 1, 0)
					local lenBelow, lenAbove = getSplitShapePlaneExtents(shape, a, b, c, nx, ny, nz);
					dist = dist - lenBelow
					local diffX = (spec.maxLength - sizeX) * 0.5 * (spec.fXRot and -1 or 1)
					local wx,wy,wz = localToWorld(spec.fillPoseNode,0,-dist - (sizeX/2) - diffX,0)
					local dx,dy,dz = worldToLocal(getParent(shape),wx,wy,wz)
					local nx, ny, nz = localDirectionToWorld(spec.fillPoseNode, 1, 0, 0)
					local yx, yy, yz = localDirectionToWorld(spec.fillPoseNode, 0, 1, 0)
					local x, y, z = worldDirectionToLocal(getParent(shape), nx, ny, nz)
					local xdir, ydir, zdir = worldDirectionToLocal(getParent(shape), yx, yy, yz)
					if numAttachments == nil then numAttachments = 0; end;
					if maxSize <= spec.loadMaxLen and maxSize >= spec.loadMinLen and numAttachments <= spec.loadMaxAtt --[[and maxSize <= (spec.maxLength + 0.2)]]  then
						removeFromPhysics(shape)
						setTranslation(shape,dx,dy,dz)
						setDirection(shape, x, y, z, xdir, ydir, zdir)
						addToPhysics(shape)
						spec.lastWoodShapes = shape
					else
						spec.badTree = shape
					end;
				end
			end
		end
	elseif spec.unload then
		spec.autoLoadElaps = spec.autoLoadElaps + dt;
		if spec.autoLoadElaps >= spec.autoLoadSpeed then
			spec.autoLoadElaps = 0;
			if self.isServer then
				local side = spec.rightSide and 2 or 1;
				local x,y,z = getWorldTranslation(spec.fillPoseNode)
				local uX,uY,uZ = getTranslation(spec.unloadPoseNode[side])
				local findWood = false;
				for k, shape in pairs(spec.woodLoad) do
					if entityExists(shape) then
						spec.shape = shape
						local sx,sy,sz = getWorldTranslation(shape)
						local dist = MathUtil.vector2Length(x - sx, z - sz)
						uX = math.abs(uX)
						if uX < spec.unloadPoseNodeX + spec.unloadShiftMax then
							uX = uX + 0.6
						else
							uX = spec.unloadPoseNodeX
						end
						setTranslation(spec.unloadPoseNode[side], (spec.rightSide and -1 or 1) * uX, uY, uZ)
						if getChild(shape,'logCenter') == 0 then
							local x,y,z = getWorldTranslation(shape)
							local nx,ny,nz = localDirectionToWorld(shape, 0,1,0);
							local lenBelow, lenAbove = getSplitShapePlaneExtents(shape, x,y,z,nx,ny,nz);
							local sizeX, sizeY, sizeZ = getSplitShapeStats(shape)
							local logCenter = createTransformGroup("logCenter")
							link(shape, logCenter)
							setTranslation(logCenter, 0,-lenBelow+(sizeX/2),0)
							spec.logCenter = logCenter
						else
							local logCenter = getChild(shape,'logCenter')
							spec.logCenter = logCenter
						end
						if dist < 100 then
							local wx,wy,wz = localToWorld(spec.unloadPoseNode[side],0,-dist,0)
							local dx,dy,dz = worldToLocal(getParent(shape),wx,wy,wz)
							local nx, ny, nz = localDirectionToWorld(spec.unloadPoseNode[side], 1, 0, 0)
							local yx, yy, yz = localDirectionToWorld(spec.unloadPoseNode[side], 0, 1, 0)
							local x, y, z = worldDirectionToLocal(getParent(shape), nx, ny, nz)
							local xdir, ydir, zdir = worldDirectionToLocal(getParent(shape), yx, yy, yz)
							removeFromPhysics(shape)
							setTranslation(shape,dx,dy,dz)
							setDirection(shape, x, y, z, xdir, ydir, zdir)
							addToPhysics(shape)
							local x,y,z = getWorldTranslation(spec.logCenter)
							local a,b,c = getWorldTranslation(spec.unloadPoseNode[side])
							local dist2 = MathUtil.vector2Length(x - a, z - c)
							if dist2 > 0 then
								local wx,wy,wz = localToWorld(spec.unloadPoseNode[side],0,-dist+dist2,0)
								local dx,dy,dz = worldToLocal(getParent(shape),wx,wy,wz)
								setTranslation(shape,dx,dy,dz)
							end
							local x,y,z = getWorldTranslation(spec.logCenter)
							local a,b,c = getWorldTranslation(spec.unloadPoseNode[side])
							local dist3 = MathUtil.vector2Length(x - a, z - c)
							if dist3 > 0 then
								local wx,wy,wz = localToWorld(spec.unloadPoseNode[side],0,-dist+dist2-dist3,0)
								local dx,dy,dz = worldToLocal(getParent(shape),wx,wy,wz)
								setTranslation(shape,dx,dy,dz)
							end
							self:dynamicMountTriggerCallback(spec.dynamicMountTrigger, shape, false, true, false, shape)
							findWood = true;
							break;
						else
							spec.woodLoad[k] = nil
						end
					else
						spec.woodLoad[k] = nil
					end
				end
				if findWood == false then
					self:toggleState(spec.autoload, spec.rightSide, false, spec.showPosition)
					setTranslation(spec.unloadPoseNode[side], spec.unloadPoseNodeX, spec.unloadPoseNodeY, spec.unloadPoseNodeZ)
				end;
			end;
		end;
	end
	if self:getIsActiveForInput() then
		if spec.event_IDs ~= nil and g_dedicatedServerInfo == nil then
			if spec.showPosition == true and spec.isClient then	
				local x,y,z = getWorldTranslation(spec.fillPoseNode)
				local a,b,c = getWorldTranslation(spec.ALWBegin)
				local dist = MathUtil.vector2Length(x - a, z - c)
				spec.fillInfoText = '|<-- '..string.format("%.1f",dist)..' m\n |'
				Utils.renderTextAtWorldPosition(x, y, z, spec.fillInfoText, getCorrectTextSize(0.016), 0);
			end
			if spec.autoload then
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_AUTO'], g_i18n:getText('ALW_STOP_AUTOLOAD'))
			else
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_AUTO'], g_i18n:getText('ALW_START_AUTOLOAD'))
			end
			if spec.unload then
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_UNLOAD'], g_i18n:getText('ALW_STOP_UNLOAD'))
			else
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_UNLOAD'], g_i18n:getText('ALW_START_UNLOAD'))
			end
			if spec.rightSide then
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_SIDE'], g_i18n:getText('ALW_SWITCH_LEFT'))
			else
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_SIDE'], g_i18n:getText('ALW_SWITCH_RIGHT'))
			end
			if spec.showPosition then
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_SHOW_POSITION'], g_i18n:getText('ALW_HIDE_POSITION'))
			else
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_SHOW_POSITION'], g_i18n:getText('ALW_SHOW_POSITION'))
			end
			if spec.showLoadPos then
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_LOAD_MARKER'], g_i18n:getText('ALW_HIDE_LOAD_MARKER'))
			else
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_LOAD_MARKER'], g_i18n:getText('ALW_SHOW_LOAD_MARKER'))
			end
			if spec.showUnloadPos then
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_UNLOAD_MARKER'], g_i18n:getText('ALW_HIDE_UNLOAD_MARKER'))
			else
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_UNLOAD_MARKER'], g_i18n:getText('ALW_SHOW_UNLOAD_MARKER'))
			end
			if ALW.showHelp then
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_HELP'], g_i18n:getText('ALW_HIDE_HELP'))
			else
				g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_HELP'], g_i18n:getText('ALW_SHOW_HELP'))
			end
			g_inputBinding:setActionEventText(spec.event_IDs['ALW_TOGGLE_PILES'], g_i18n:getText('input_ALW_TOGGLE_PILES')..' : '..spec.numPiles..' (max. '..spec.maxLength..' m)')
			g_inputBinding:setActionEventText(spec.event_IDs['ALW_SWITCH_PILE'], g_i18n:getText('input_ALW_SWITCH_PILE')..' : '..spec.pile)
			g_inputBinding:setActionEventText(spec.event_IDs['ALW_UNLOAD_MARKER_MOVE'], g_i18n:getText('input_ALW_UNLOAD_MARKER_MOVE')..' : '..math.ceil(spec.unloadRot and spec.unloadPos or spec.unloadPos-1)..'/'..math.ceil(spec.unloadRot and spec.rootShiftRotXMax or 4)..' m')
			g_inputBinding:setActionEventText(spec.event_IDs['ALW_UNLOAD_MARKER_SCALE'], g_i18n:getText('input_ALW_UNLOAD_MARKER_SCALE')..' : '..math.ceil(spec.unloadScale*4.8)..'/'..math.ceil(2*4.8)..' m')
			
			for i,eventID in pairs(spec.event_IDs) do
			if i ~= InputAction.ALW_TOGGLE_HELP and i ~= InputAction.RC_TOGGLE and i ~= InputAction.RC_TOGGLE_ALL then
				if ALW.showHelp then
					if i == InputAction.ALW_UNLOAD_MARKER_MOVE or i == InputAction.ALW_UNLOAD_MARKER_SCALE or i == InputAction.ALW_UNLOAD_MARKER_ROTATE then
						g_inputBinding:setActionEventTextVisibility(eventID, spec.showUnloadPos)
					else
						g_inputBinding:setActionEventTextVisibility(eventID, ALW.showHelp)
					end
				else
					g_inputBinding:setActionEventTextVisibility(eventID, ALW.showHelp)
				end
			end
		end
		end
	end
end
function ALW:onDraw()
	local spec = self.spec_ALW
end
function ALW:toggleState(autoload, rightSide, unload, noEventSend)
	local spec = self.spec_ALW
	
	ALWToggleEvent.sendEvent(self, autoload, rightSide, unload, noEventSend)
	
	if rightSide ~= spec.rightSide then
		unlink(spec.unloadMarker)
		rotate(spec.unloadMarker, 0,math.rad(180),0)
		local mX,mY,mZ = getTranslation(spec.unloadMarker)
		mX = mX * -1
		link(spec.unloadPoseRoot[rightSide and 2 or 1], spec.unloadMarker);
	end
	
	spec.lastWoodShapes = 0;
	spec.autoload = autoload;
	spec.rightSide = rightSide;
	spec.unload = unload;
end;
function ALW:toggleLoad(showLoadPos, numPiles, pile, showPosition, noEventSend)
	local spec = self.spec_ALW
	
	ALWToggleLoadEvent.sendEvent(self, showLoadPos, numPiles, pile, showPosition, noEventSend)
	
	spec.showLoadPos = showLoadPos
	spec.numPiles = numPiles
	spec.pile = pile
	spec.showPosition = showPosition
	self:updateValues()
	self:updateLoad()
	self:updateUnload()
end
function ALW:toggleUnload(showUnloadPos, unloadPos, unloadScale, unloadRot, noEventSend)
	local spec = self.spec_ALW
	
	ALWToggleUnloadEvent.sendEvent(self, showUnloadPos, unloadPos, unloadScale, unloadRot, noEventSend)
	
	if unloadPos ~= spec.unloadPos or unloadRot ~= spec.unloadRot then
		setTranslation(spec.unloadPoseNode[spec.rightSide and 2 or 1], spec.unloadPoseNodeX, spec.unloadPoseNodeY, spec.unloadPoseNodeZ)
	end
	
	spec.showUnloadPos = showUnloadPos
	spec.unloadPos = unloadPos
	spec.unloadScale = unloadScale
	spec.unloadRot = unloadRot
	self:updateValues()
	self:updateUnload()
end
function ALW:actionCallback(actionName, keyStatus, arg4, arg5, arg6)
	local spec = self.spec_ALW
	if keyStatus > 0 then
		if actionName == 'ALW_TOGGLE_AUTO' then
			self:toggleState(not spec.autoload, spec.rightSide, false)
		elseif actionName == 'ALW_TOGGLE_UNLOAD' then
			self:toggleState(false, spec.rightSide, not spec.unload)
		elseif actionName == 'ALW_TOGGLE_SIDE' then
			self:toggleState(false, not spec.rightSide, false)
		elseif actionName == 'ALW_TOGGLE_SHOW_POSITION' then
			self:toggleLoad(spec.showLoadPos, spec.numPiles, spec.pile, not spec.showPosition)
		elseif actionName == 'ALW_TOGGLE_PILES' then
			if spec.numPiles + 1 <= spec.maxPiles then
				spec.numPiles = spec.numPiles + 1
			else
				spec.numPiles = 1
			end
			self:toggleLoad(spec.showLoadPos, spec.numPiles, 1, spec.showPosition)
			self:toggleState(false, spec.rightSide, false)
			if spec.unloadRot then
				spec.unloadPos = spec.rootShiftRotX
			end
			self:toggleUnload(spec.showUnloadPos, spec.unloadPos, spec.unloadScale, spec.unloadRot)
		elseif actionName == 'ALW_SWITCH_PILE' then
			if spec.pile + 1 <= spec.numPiles then
				spec.pile = spec.pile + 1
			else
				spec.pile = 1
			end
			self:toggleLoad(spec.showLoadPos, spec.numPiles, spec.pile, spec.showPosition)
		elseif actionName == 'ALW_TOGGLE_LOAD_MARKER' then
			self:toggleLoad(not spec.showLoadPos, spec.numPiles, spec.pile, spec.showPosition)
		elseif actionName == 'ALW_TOGGLE_UNLOAD_MARKER' then
			self:toggleUnload(not spec.showUnloadPos, spec.unloadPos, spec.unloadScale, spec.unloadRot)
		elseif actionName == 'ALW_UNLOAD_MARKER_MOVE' then
			local rX,rY,rZ = getTranslation(spec.unloadPoseRoot[1])
			if spec.unloadRot == true then
				rX = math.ceil(math.abs(rX))
				if rX < spec.rootShiftRotXMax then
					rX = rX + 1
				else
					rX = spec.rootShiftRotX
				end
			else
				rX = math.ceil(math.abs(rX))
				if rX < 5 then
					rX = rX + 1
				else
					rX = spec.unloadPoseRootX
				end
			end
			local unloadPos = rX
			self:toggleUnload(spec.showUnloadPos, unloadPos, spec.unloadScale, spec.unloadRot)
		elseif actionName == 'ALW_UNLOAD_MARKER_SCALE' then
			local msX,msY,msZ = getScale(spec.unloadMarker)
			if msZ < 2 then
				msZ = msZ + 0.2
			else
				msZ = 1
			end
			spec.unloadScale = msZ
			self:toggleUnload(spec.showUnloadPos, spec.unloadPos, spec.unloadScale, spec.unloadRot)
		elseif actionName == 'ALW_UNLOAD_MARKER_ROTATE' then
			if spec.unloadRot == false then
				spec.unloadPos = spec.rootShiftRotX
			else
				spec.unloadPos = spec.unloadPoseRootX
			end
			self:toggleUnload(spec.showUnloadPos, spec.unloadPos, spec.unloadScale, not spec.unloadRot)
		elseif actionName == 'ALW_TOGGLE_HELP' then
			ALW.showHelp = not ALW.showHelp
			self:saveToXml();
		end
	end
end
function ALW:updateValues()
	local spec = self.spec_ALW
	spec.unloadShiftMax = spec.unloadScale * 4
	if spec.trailer == 8 then
		spec.maxPiles = 2
		if spec.numPiles == 1 then
			spec.maxLength = 6
			spec.startPosZ = 0.15;
			spec.rootShiftRotX = 5
			spec.rootShiftRotXMax = 8
		elseif spec.numPiles == 2 then
			spec.maxLength = 3
			spec.startPosZ = 1.6;
			spec.rootShiftRotX = 3
			spec.rootShiftRotXMax = 6
			if spec.pile == 1 then
				spec.startPosZ = spec.startPosZ;
			elseif spec.pile == 2 then
				spec.startPosZ = spec.startPosZ - spec.maxLength - spec.space
			end
		end
	elseif spec.trailer == 12 then
		spec.maxPiles = 3
		if spec.numPiles == 1 then
			spec.maxLength = 12
			spec.startPosZ = -4.2;
			spec.rootShiftRotX = 8
			spec.rootShiftRotXMax = 11
		elseif spec.numPiles == 2 then
			spec.maxLength = 6
			spec.startPosZ = -1.2;
			spec.rootShiftRotX = 5
			spec.rootShiftRotXMax = 8
			if spec.pile == 1 then
				spec.startPosZ = spec.startPosZ;
			elseif spec.pile == 2 then
				spec.startPosZ = spec.startPosZ - spec.maxLength - spec.space
			end
		elseif spec.numPiles == 3 then
			spec.maxLength = 4
			spec.startPosZ = -0.2
			spec.rootShiftRotX = 4
			spec.rootShiftRotXMax = 7
			if spec.pile == 1 then
				spec.startPosZ = spec.startPosZ;
			elseif spec.pile == 2 then
				spec.startPosZ = spec.startPosZ - spec.maxLength - spec.space
			elseif spec.pile == 3 then
				spec.startPosZ = spec.startPosZ - (2 * (spec.maxLength + spec.space))
			end
		end
	elseif spec.trailer == 15 then
		spec.maxPiles = 4
		if spec.numPiles == 1 then
			spec.maxLength = 15
			spec.startPosZ = -4.2;
			spec.rootShiftRotX = 9.65
			spec.rootShiftRotXMax = 12.8
		elseif spec.numPiles == 2 then
			spec.maxLength = 7.5
			spec.startPosZ = -0.45;
			spec.rootShiftRotX = 5.9
			spec.rootShiftRotXMax = 8.9
			if spec.pile == 1 then
				spec.startPosZ = spec.startPosZ;
			elseif spec.pile == 2 then
				spec.startPosZ = spec.startPosZ - spec.maxLength - spec.space
			end
		elseif spec.numPiles == 3 then
			spec.maxLength = 5
			spec.startPosZ = 0.8
			spec.rootShiftRotX = 4.6
			spec.rootShiftRotXMax = 7.6
			if spec.pile == 1 then
				spec.startPosZ = spec.startPosZ;
			elseif spec.pile == 2 then
				spec.startPosZ = spec.startPosZ - spec.maxLength - spec.space
			elseif spec.pile == 3 then
				spec.startPosZ = spec.startPosZ - (2 * (spec.maxLength + spec.space))
			end
		elseif spec.numPiles == 4 then
			spec.maxLength = 3.5
			spec.startPosZ = 1.55
			spec.rootShiftRotX = 3.9
			spec.rootShiftRotXMax = 6.9
			if spec.pile == 1 then
				spec.startPosZ = spec.startPosZ;
			elseif spec.pile == 2 then
				spec.startPosZ = spec.startPosZ - spec.maxLength - spec.space
			elseif spec.pile == 3 then
				spec.startPosZ = spec.startPosZ - (2 * (spec.maxLength + spec.space))
			elseif spec.pile == 4 then
				spec.startPosZ = spec.startPosZ - (3 * (spec.maxLength + spec.space))
			end
		end
	elseif spec.trailer == 20 then
		spec.maxPiles = 4
		if spec.numPiles == 1 then
			spec.maxLength = 20
			spec.startPosZ = -4.1;
			spec.rootShiftRotX = 12.3
			spec.rootShiftRotXMax = 15.3
		elseif spec.numPiles == 2 then
			spec.maxLength = 10
			spec.startPosZ = 0.9;
			spec.rootShiftRotX = 7.3
			spec.rootShiftRotXMax = 10.3
			if spec.pile == 1 then
				spec.startPosZ = spec.startPosZ;
			elseif spec.pile == 2 then
				spec.startPosZ = spec.startPosZ - spec.maxLength - spec.space
			end
		elseif spec.numPiles == 3 then
			spec.maxLength = 6.5
			spec.startPosZ = 2.65
			spec.rootShiftRotX = 5.55
			spec.rootShiftRotXMax = 8.55
			if spec.pile == 1 then
				spec.startPosZ = spec.startPosZ;
			elseif spec.pile == 2 then
				spec.startPosZ = spec.startPosZ - spec.maxLength - spec.space
			elseif spec.pile == 3 then
				spec.startPosZ = spec.startPosZ - (2 * (spec.maxLength + spec.space))
			end
		elseif spec.numPiles == 4 then
			spec.maxLength = 5
			spec.startPosZ = 3.4
			spec.rootShiftRotX = 4.8
			spec.rootShiftRotXMax = 7.8
			if spec.pile == 1 then
				spec.startPosZ = spec.startPosZ;
			elseif spec.pile == 2 then
				spec.startPosZ = spec.startPosZ - spec.maxLength - spec.space
			elseif spec.pile == 3 then
				spec.startPosZ = spec.startPosZ - (2 * (spec.maxLength + spec.space))
			elseif spec.pile == 4 then
				spec.startPosZ = spec.startPosZ - (3 * (spec.maxLength + spec.space))
			end
		end
	end
end
function ALW:updateLoad()
	local spec = self.spec_ALW
	
	setTranslation(spec.fillPoseRoot, spec.fillPoseNodeX, spec.fillPoseNodeY, spec.startPosZ)
	setScale(spec.loadMarker, spec.maxLength,1,2.5)
	setVisibility(spec.loadMarker, spec.showLoadPos);
	setScale(spec.unloadMarker, spec.maxLength,1,spec.unloadScale)
end
function ALW:updateUnload()
	local spec = self.spec_ALW
	
	local j = 1
	for i = 1, 2 do
		setRotation(spec.unloadPoseRoot[i], 0,(spec.unloadRot and math.rad(90) or math.rad(0)) * j,0)
		setTranslation(spec.unloadPoseRoot[i], spec.unloadPos * j, 0, (spec.unloadRot and 3 or spec.unloadPoseRootZ))
		j = j * -1
	end
	setScale(spec.unloadMarker, spec.maxLength,1,spec.unloadScale)
	setVisibility(spec.unloadMarker, spec.showUnloadPos);
end
function ALW:dynamicMountTriggerCallback(superFunc,triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
	local spec = self.spec_ALW
	local splitType = g_splitTypeManager:getSplitTypeByIndex(getSplitType(otherActorId))
	if splitType ~= nil then
		if onEnter then
			if not spec.unload then
				spec.woodLoad[otherActorId] = otherActorId
			end
		elseif onLeave then
			spec.woodLoad[otherActorId] = nil;
		end
	end
	--superFunc(spec, triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
end
function ALW:getIsTurnedOn()
	local spec = self.spec_ALW
    return spec.autoload or spec.unload
end
function ALW:onReadStream(streamId, connection)
	local spec = self.spec_ALW
	
	local rightSide = streamReadBool(streamId);
	local showLoadPos = streamReadBool(streamId);
	local showUnloadPos = streamReadBool(streamId);
	local numPiles = streamReadInt8(streamId);
    local pile = streamReadInt8(streamId);
    local unloadPos = streamReadFloat32(streamId);
    local unloadScale = streamReadFloat32(streamId);
    local unloadRot = streamReadBool(streamId);
    local showPosition = streamReadBool(streamId);
	
	if rightSide ~= nil and showLoadPos ~= nil and showUnloadPos ~= nil and numPiles ~= nil and pile ~= nil and unloadPos ~= nil and unloadScale ~= nil and unloadRot ~= nil and showPosition ~= nil then
		self:toggleState(spec.autoload, rightSide, spec.unload, true)
		self:toggleLoad(showLoadPos, numPiles, pile, showPosition, true)
		self:toggleUnload(showUnloadPos, unloadPos, unloadScale, unloadRot, true)
	end
end;

function ALW:onWriteStream(streamId, connection)
	local spec = self.spec_ALW
	
	streamWriteBool(streamId, spec.rightSide);
	streamWriteBool(streamId, spec.showLoadPos);
	streamWriteBool(streamId, spec.showUnloadPos);
	streamWriteInt8(streamId, spec.numPiles);
	streamWriteInt8(streamId, spec.pile);
	streamWriteFloat32(streamId, spec.unloadPos);
	streamWriteFloat32(streamId, spec.unloadScale);
	streamWriteBool(streamId, spec.unloadRot);
	streamWriteBool(streamId, spec.showPosition);
end;

--- Events ---

ALWToggleEvent = {};
ALWToggleEvent_mt = Class(ALWToggleEvent, Event);

InitEventClass(ALWToggleEvent, "ALWToggleEvent");

function ALWToggleEvent:emptyNew()
    local self = Event:new(ALWToggleEvent_mt);
    return self;
end;
    
function ALWToggleEvent:new(object, autoload, rightSide, unload)
	local self = ALWToggleEvent:emptyNew()
	self.object = object;
	self.autoload = autoload;
	self.rightSide = rightSide;
	self.unload = unload;
	return self;
end;

function ALWToggleEvent:readStream(streamId, connection)
	self.object = NetworkUtil.readNodeObject(streamId);
	self.autoload = streamReadBool(streamId);
	self.rightSide = streamReadBool(streamId);
	self.unload = streamReadBool(streamId);
	self:run(connection);
end;

function ALWToggleEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.object);
	streamWriteBool(streamId, self.autoload);
	streamWriteBool(streamId, self.rightSide);
	streamWriteBool(streamId, self.unload);
end;

function ALWToggleEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object);
	end;
	if self.object ~= nil then
		self.object:toggleState(self.autoload, self.rightSide, self.unload, true);
	end;
end;

function ALWToggleEvent.sendEvent(vehicle, autoload, rightSide, unload, noEventSend)
	if autoload ~= vehicle.autoload or rightSide ~= vehicle.rightSide or unload ~= vehicle.unload then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(ALWToggleEvent:new(vehicle, autoload, rightSide, unload), nil, nil, vehicle);
			else
				g_client:getServerConnection():sendEvent(ALWToggleEvent:new(vehicle, autoload, rightSide, unload));
			end;
		end;
	end;
end;

ALWToggleLoadEvent = {};
ALWToggleLoadEvent_mt = Class(ALWToggleLoadEvent, Event);

InitEventClass(ALWToggleLoadEvent, "ALWToggleLoadEvent");

function ALWToggleLoadEvent:emptyNew()
    local self = Event:new(ALWToggleLoadEvent_mt);
    return self;
end;
    
function ALWToggleLoadEvent:new(object, showLoadPos, numPiles, pile, showPosition)
	local self = ALWToggleLoadEvent:emptyNew()
	self.object = object;
	self.showLoadPos = showLoadPos;
	self.numPiles = numPiles;
	self.pile = pile;
	self.showPosition = showPosition;
	return self;
end;

function ALWToggleLoadEvent:readStream(streamId, connection)
	self.object = NetworkUtil.readNodeObject(streamId);
	self.showLoadPos = streamReadBool(streamId);
	self.numPiles = streamReadInt8(streamId);
	self.pile = streamReadInt8(streamId);
	self.showPosition = streamReadBool(streamId);
	self:run(connection);
end;

function ALWToggleLoadEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.object);
	streamWriteBool(streamId, self.showLoadPos);
	streamWriteInt8(streamId, self.numPiles);
	streamWriteInt8(streamId, self.pile);
	streamWriteBool(streamId, self.showPosition);
end;

function ALWToggleLoadEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object);
	end;
	if self.object ~= nil then
		self.object:toggleLoad(self.showLoadPos, self.numPiles, self.pile, self.showPosition, true);
	end;
end;

function ALWToggleLoadEvent.sendEvent(vehicle, showLoadPos, numPiles, pile, showPosition, noEventSend)
	if showLoadPos ~= vehicle.showLoadPos or numPiles ~= vehicle.numPiles or pile ~= vehicle.pile or showPosition ~= vehicle.showPosition then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(ALWToggleLoadEvent:new(vehicle, showLoadPos, numPiles, pile, showPosition), nil, nil, vehicle);
			else
				g_client:getServerConnection():sendEvent(ALWToggleLoadEvent:new(vehicle, showLoadPos, numPiles, pile, showPosition));
			end;
		end;
	end;
end;

ALWToggleUnloadEvent = {};
ALWToggleUnloadEvent_mt = Class(ALWToggleUnloadEvent, Event);

InitEventClass(ALWToggleUnloadEvent, "ALWToggleUnloadEvent");

function ALWToggleUnloadEvent:emptyNew()
    local self = Event:new(ALWToggleUnloadEvent_mt);
    return self;
end;
    
function ALWToggleUnloadEvent:new(object, showUnloadPos, unloadPos, unloadScale, unloadRot)
	local self = ALWToggleUnloadEvent:emptyNew()
	self.object = object;
	self.showUnloadPos = showUnloadPos;
	self.unloadPos = unloadPos;
	self.unloadScale = unloadScale;
	self.unloadRot = unloadRot;
	return self;
end;

function ALWToggleUnloadEvent:readStream(streamId, connection)
	self.object = NetworkUtil.readNodeObject(streamId);
	self.showUnloadPos = streamReadBool(streamId);
	self.unloadPos = streamReadFloat32(streamId);
	self.unloadScale = streamReadFloat32(streamId);
	self.unloadRot = streamReadBool(streamId);
	self:run(connection);
end;

function ALWToggleUnloadEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.object);
	streamWriteBool(streamId, self.showUnloadPos);
	streamWriteFloat32(streamId, self.unloadPos);
	streamWriteFloat32(streamId, self.unloadScale);
	streamWriteBool(streamId, self.unloadRot);
end;

function ALWToggleUnloadEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object);
	end;
	if self.object ~= nil then
		self.object:toggleUnload(self.showUnloadPos, self.unloadPos, self.unloadScale, self.unloadRot, true);
	end;
end;

function ALWToggleUnloadEvent.sendEvent(vehicle, showUnloadPos, unloadPos, unloadScale, unloadRot, noEventSend)
	if showUnloadPos ~= vehicle.showUnloadPos or unloadPos ~= vehicle.unloadPos or unloadScale ~= vehicle.unloadScale or unloadRot ~= vehicle.unloadRot then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(ALWToggleUnloadEvent:new(vehicle, showUnloadPos, unloadPos, unloadScale, unloadRot), nil, nil, vehicle);
			else
				g_client:getServerConnection():sendEvent(ALWToggleUnloadEvent:new(vehicle, showUnloadPos, unloadPos, unloadScale, unloadRot));
			end;
		end;
	end;
end;