diff --git a/AIDriver.lua b/AIDriver.lua index 84cfc7b81..a68dee4f5 100644 --- a/AIDriver.lua +++ b/AIDriver.lua @@ -154,7 +154,7 @@ function AIDriver:init(vehicle) end self.aiDriverData = vehicle.cp.aiDriverData self:debug('creating AIDriver') - self.maxDrivingVectorLength = self.vehicle.cp.turnDiameter + self.maxDrivingVectorLength = self.vehicle.cp.settings.turnDiameter:get() ---@type PurePursuitController self.ppc = PurePursuitController(self.vehicle) self.vehicle.cp.ppc = self.ppc @@ -177,6 +177,7 @@ function AIDriver:init(vehicle) self.activeMsgReferences = {} self.settings = self.vehicle.cp.settings + self.courseGeneratorSettings = self.vehicle.cp.courseGeneratorSettings -- make sure all vehicle settings are valid for this mode if self.settings then self:debug('Validating current settings...') @@ -969,7 +970,7 @@ end ---@param course Course function AIDriver:isAlignmentCourseNeeded(course, ix) local d = course:getDistanceBetweenVehicleAndWaypoint(self.vehicle, ix) - return d > self.vehicle.cp.turnDiameter + return d > self.settings.turnDiameter:get() end function AIDriver:startTurn(ix) @@ -1557,7 +1558,8 @@ function AIDriver:startCourseWithPathfinding(course, ix, zOffset, fieldNum, alwa local d = course:getDistanceBetweenVehicleAndWaypoint(self.vehicle, ix) -- always enforce a minimum distance needed for pathfinding, otherwise we'll end up with vehicles making -- a circle just to end up 50 cm to the left or right... - local pathfindingRange = alwaysUsePathfinding and self.vehicle.cp.turnDiameter or (3 * self.vehicle.cp.turnDiameter) + local turnDiameter = self.settings.turnDiameter:get() + local pathfindingRange = alwaysUsePathfinding and turnDiameter or (3 * turnDiameter) if not alwaysUsePathfinding and d < pathfindingRange then self:debug('Too close to target (%.1fm), will not perform pathfinding', d) return self:startCourseWithAlignment(course, ix) diff --git a/AIDriverUtil.lua b/AIDriverUtil.lua index 1811a36e4..3354e9d7e 100644 --- a/AIDriverUtil.lua +++ b/AIDriverUtil.lua @@ -69,7 +69,8 @@ function AIDriverUtil.calculateTightTurnOffset(vehicle, course, previousOffset, -- limit the radius we are trying to follow to the vehicle's turn radius. -- TODO: there's some potential here as the towed implement can move on a radius less than the vehicle's -- turn radius so this limit may be too pessimistic - r = math.max(r, vehicle.cp.turnDiameter / 2) + local turnDiameter = vehicle.cp.settings.turnDiameter:get() + r = math.max(r, turnDiameter / 2) local towBarLength = AIDriverUtil.getTowBarLength(vehicle) @@ -173,8 +174,10 @@ function AIDriverUtil.getTurningRadius(vehicle) radius = g_vehicleConfigurations:get(vehicle, 'turnRadius') courseplay.debugVehicle(courseplay.DBG_IMPLEMENTS, vehicle, ' turnRadius set from configfile to %.1f', radius) end - if vehicle.cp.turnDiameterAutoMode == false and vehicle.cp.turnDiameter ~= nil then - radius = vehicle.cp.turnDiameter / 2 + + local turnDiameterSetting = vehicle.cp.settings.turnDiameter + if not turnDiameterSetting:isAutomaticActive() then + radius = turnDiameterSetting:get() / 2 courseplay.debugVehicle(courseplay.DBG_IMPLEMENTS, vehicle, ' turnRadius manually set to %.1f', radius) end diff --git a/AITurn.lua b/AITurn.lua index d71b28856..73587ecb7 100644 --- a/AITurn.lua +++ b/AITurn.lua @@ -112,9 +112,10 @@ function AITurn.canMakeKTurn(vehicle, turnContext) courseplay.debugVehicle(AITurn.debugChannel, vehicle, 'Headland turn, let turn.lua drive for now.') return false end - if vehicle.cp.turnDiameter <= math.abs(turnContext.dx) then + local turnDiameter = vehicle.cp.settings.turnDiameter:get() + if turnDiameter <= math.abs(turnContext.dx) then courseplay.debugVehicle(AITurn.debugChannel, vehicle, 'wide turn with no reversing (turn diameter = %.1f, dx = %.1f, let turn.lua do that for now.', - vehicle.cp.turnDiameter, math.abs(turnContext.dx)) + turnDiameter, math.abs(turnContext.dx)) return true end if not AIVehicleUtil.getAttachedImplementsAllowTurnBackward(vehicle) then @@ -248,8 +249,8 @@ function KTurn:turn(dt) end AITurn.turn(self) - - local turnRadius = self.vehicle.cp.turnDiameter / 2 + local turnDiameter = self.vehicle.cp.settings.turnDiameter:get() + local turnRadius = turnDiameter / 2 if self.state == self.states.FORWARD then local dx, _, dz = self.turnContext:getLocalPositionFromTurnEnd(self.driver:getDirectionNode()) self:setForwardSpeed() @@ -337,7 +338,8 @@ function CombineHeadlandTurn:init(vehicle, driver, turnContext) self:addState('FORWARD') self:addState('REVERSE_STRAIGHT') self:addState('REVERSE_ARC') - self.turnRadius = self.vehicle.cp.turnDiameter / 2 + local turnDiameter = self.vehicle.cp.settings.turnDiameter:get() + self.turnRadius = turnDiameter / 2 self.cornerAngleToTurn = turnContext:getCornerAngleToTurn() self.angleToTurnInReverse = math.abs(self.cornerAngleToTurn / 2) self.dxToStartReverseTurn = self.turnRadius - math.abs(self.turnRadius - self.turnRadius * math.cos(self.cornerAngleToTurn)) @@ -630,7 +632,8 @@ end ---@param turnContext TurnContext function CombinePocketHeadlandTurn:generatePocketHeadlandTurn(turnContext) local cornerWaypoints = {} - local turnRadius = self.vehicle.cp.turnDiameter / 2 + local turnDiameter = self.vehicle.cp.settings.turnDiameter:get() + local turnRadius = turnDiameter / 2 -- this is how far we have to cut into the next headland (the position where the header will be after the turn) local offset = math.min(turnRadius + turnContext.frontMarkerDistance, self.vehicle.cp.workWidth) local corner = turnContext:createCorner(self.vehicle, turnRadius) diff --git a/BaleCollectorAIDriver.lua b/BaleCollectorAIDriver.lua index 632db7943..bcef2a30f 100644 --- a/BaleCollectorAIDriver.lua +++ b/BaleCollectorAIDriver.lua @@ -154,7 +154,7 @@ function BaleCollectorAIDriver:findClosestBale(bales) if bale:isStillValid() then local _, _, _, d = bale:getPositionInfoFromNode(AIDriverUtil.getDirectionNode(self.vehicle)) self:debug('%d. bale (%d, %s) in %.1f m', i, bale:getId(), bale:getBaleObject(), d) - if d < self.vehicle.cp.turnDiameter * 2 then + if d < self.settings.turnDiameter:get() * 2 then -- if it is really close, check the length of the Dubins path -- as we may need to drive a loop first to get to it d = self:getDubinsPathLengthToBale(bale) diff --git a/CombineAIDriver.lua b/CombineAIDriver.lua index 6219b6410..59b290c3a 100644 --- a/CombineAIDriver.lua +++ b/CombineAIDriver.lua @@ -90,7 +90,7 @@ function CombineAIDriver:init(vehicle) self.pullBackRightSideOffset = math.abs(self.pipeOffsetX) - self.vehicle.cp.workWidth / 2 + 5 self.pullBackRightSideOffset = self.pipeOnLeftSide and self.pullBackRightSideOffset or -self.pullBackRightSideOffset -- should be at pullBackRightSideOffset to the right or left at pullBackDistanceStart - self.pullBackDistanceStart = self.vehicle.cp.turnDiameter --* 0.7 + self.pullBackDistanceStart = self.settings.turnDiameter:get() --* 0.7 -- and back up another bit self.pullBackDistanceEnd = self.pullBackDistanceStart + 5 -- when making a pocket, how far to back up before changing to forward diff --git a/CombineUnloadAIDriver.lua b/CombineUnloadAIDriver.lua index a627959d1..55df7648c 100644 --- a/CombineUnloadAIDriver.lua +++ b/CombineUnloadAIDriver.lua @@ -446,7 +446,7 @@ function CombineUnloadAIDriver:driveOnField(dt) elseif self.onFieldState == self.states.MOVE_BACK_FULL then local _, dx, dz = self:getDistanceFromCombine(self.combineJustUnloaded) -- drive back way further if we are behind a chopper to have room - local dDriveBack = math.abs(dx) < 3 and 0.75 * self.vehicle.cp.turnDiameter or -10 + local dDriveBack = math.abs(dx) < 3 and 0.75 * self.settings.turnDiameter:get() or -10 if dz > dDriveBack then self:startUnloadCourse() end @@ -1496,7 +1496,7 @@ function CombineUnloadAIDriver:startPathfindingToTurnEnd(xOffset, zOffset) local turnEndNode, startOffset, goalOffset = self.turnContext:getTurnEndNodeAndOffsets(self.vehicle) -- ignore combine for pathfinding, it is moving anyway and our turn functions make sure we won't hit it self.pathfinder, done, path, goalNodeInvalid = PathfinderUtil.findPathForTurn(self.vehicle, startOffset, turnEndNode, goalOffset, - self.vehicle.cp.turnDiameter / 2, self:getAllowReversePathfinding(), self.followCourse, {self.combineToUnload}) + self.settings.turnDiameter:get() / 2, self:getAllowReversePathfinding(), self.followCourse, {self.combineToUnload}) if done then return self:onPathfindingDoneToTurnEnd(path, goalNodeInvalid) else diff --git a/DevHelper.lua b/DevHelper.lua index 835eef695..62a360028 100644 --- a/DevHelper.lua +++ b/DevHelper.lua @@ -195,7 +195,7 @@ function DevHelper:startPathfinding() if self.vehicle and self.vehicle.cp.driver and self.vehicle.cp.driver.fieldworkCourse then self:debug('Starting pathfinding for turn between %s and %s', tostring(self.start), tostring(self.goal)) self.pathfinder, done, path = PathfinderUtil.findPathForTurn(self.vehicle, 0, self.goalNode, 0, - 1.05 * self.vehicle.cp.turnDiameter / 2, false, self.vehicle.cp.driver.fieldworkCourse) + 1.05 * self.vehicle.cp.settings.turnDiameter:get() / 2, false, self.vehicle.cp.driver.fieldworkCourse) else self:debug('Starting pathfinding (no reverse) between %s and %s, field %d', tostring(self.start), tostring(self.goal), self.fieldNumForPathfinding or 0) diff --git a/Events/GlobalSettingsEvent.lua b/Events/GlobalSettingsEvent.lua deleted file mode 100644 index 5bfb4ec9c..000000000 --- a/Events/GlobalSettingsEvent.lua +++ /dev/null @@ -1,60 +0,0 @@ - -GlobalSettingsEvent = {}; -local GlobalSettingsEvent_mt = Class(GlobalSettingsEvent, Event); -InitEventClass(GlobalSettingsEvent, "GlobalSettingsEvent"); -function GlobalSettingsEvent:emptyNew() - local self = Event:new(GlobalSettingsEvent_mt); - self.className = "GlobalSettingsEvent"; - return self; -end - -function GlobalSettingsEvent:new(parentName, name, value) - courseplay:debug(string.format("GlobalSettingsEvent:new %s, %s, %s)", tostring(parentName),tostring(name), tostring(value)), courseplay.DBG_MULTIPLAYER) - self.parentName = parentName - self.name = name - self.value = value; - return self; -end - -function GlobalSettingsEvent:writeStream(streamId, connection) - courseplay:debug("SettingsListEvent:writeStream()",courseplay.DBG_MULTIPLAYER) - courseplay:debug(('parentName:%s, name:%s, value:%s'):format(tostring(self.parentName), tostring(self.name), tostring(self.value)), courseplay.DBG_MULTIPLAYER); - - streamWriteString(streamId, self.parentName) - streamWriteString(streamId, self.name) - streamWriteInt32(streamId, self.value) -end - -function GlobalSettingsEvent:readStream(streamId, connection) - self.parentName = streamReadString(streamId) - self.name = streamReadString(streamId) - self.value = streamReadInt32(streamId) - - courseplay:debug("GlobalSettingsEvent:readStream()",courseplay.DBG_MULTIPLAYER) - courseplay:debug(('parentName:%s, name:%s, value:%s'):format(tostring(self.parentName), tostring(self.name), tostring(self.value)), courseplay.DBG_MULTIPLAYER); - - self:run(connection) -end - -function GlobalSettingsEvent:run(connection) - courseplay:debug("GlobalSettingsEvent:run()",courseplay.DBG_MULTIPLAYER) - courseplay:debug(('parentName:%s, name:%s, value:%s'):format(tostring(self.parentName), tostring(self.name), tostring(self.value)), courseplay.DBG_MULTIPLAYER); - courseplay[self.parentName][self.name]:setFromNetwork(self.value) - - if not connection:getIsServer() then - courseplay:debug("broadcast GlobalSettingsEvent",courseplay.DBG_MULTIPLAYER) - g_server:broadcastEvent(GlobalSettingsEvent:new(self.parentName, self.name, self.value), nil, connection); - end; -end - -function GlobalSettingsEvent.sendEvent(parentName, name, value) - if g_server == nil then - courseplay:debug("send GlobalSettingsEvent", courseplay.DBG_MULTIPLAYER) - courseplay:debug(('parentName:%s, name:%s, value:%s'):format(tostring(parentName), tostring(name), tostring(value)), courseplay.DBG_MULTIPLAYER); - g_client:getServerConnection():sendEvent(GlobalSettingsEvent:new(parentName, name, value)) - else - courseplay:debug("broadcast GlobalSettingsEvent", courseplay.DBG_MULTIPLAYER) - courseplay:debug(('parentName:%s, name:%s, value:%s'):format(tostring(parentName), tostring(name), tostring(value)), courseplay.DBG_MULTIPLAYER); - g_server:broadcastEvent(GlobalSettingsEvent:new(parentName, name, value)) - end -end \ No newline at end of file diff --git a/Events/SettingEvent.lua b/Events/SettingEvent.lua new file mode 100644 index 000000000..fd1b0356c --- /dev/null +++ b/Events/SettingEvent.lua @@ -0,0 +1,141 @@ +--- This event is used to synchronize Setting changes on run time. +--- Every setting event requires: +--- - a container name (parentName) +--- - a setting name +--- - an event index for the setting +--- - the value +--- +SettingEvent = {} +local SettingEvent_mt = Class(SettingEvent, Event) + +InitEventClass(SettingEvent, "SettingEvent") + +function SettingEvent:emptyNew() + local self = Event:new(SettingEvent_mt) + self.className = "SettingEvent" + return self +end + +--- Creates a new Event +---@param vehicle table +---@param setting Setting +---@param eventData table +---@param value any +function SettingEvent:new(vehicle,setting,eventData,value) + self.vehicle = vehicle + self.value = value + self.parentName,self.name,self.eventIx,self.writeFunc = self.decodeEventData(setting,eventData) + self.debug("SettingEvent:new()") + return self +end + +--- Reads the serialized data on the receiving end of the event. +function SettingEvent:readStream(streamId, connection) -- wird aufgerufen wenn mich ein Event erreicht + self.vehicle = nil + if streamReadBool(streamId) then + self.vehicle = NetworkUtil.getObject(streamReadInt32(streamId)) + self.debugVehicle(self.vehicle,"Vehicle setting") + else + self.debug("Global setting") + end + + self.parentName = streamReadString(streamId) + self.name = streamReadString(streamId) + self.eventIx = streamReadUInt8(streamId) + + self.setting,self.eventData = self.encodeEventData(self.vehicle,self.parentName,self.name,self.eventIx) + + if self.eventData.readFunc then + self.value = self.eventData.readFunc(streamId) + end + + self.debug("SettingEvent:readStream()") + self.debug("Parent name: %s, Setting name: %s, value: %s, eventIx: %d",self.parentName, self.name, tostring(self.value),self.eventIx) + + self:run(connection); +end + +--- Writes the serialized data from the sender. +function SettingEvent:writeStream(streamId, connection) -- Wird aufgrufen wenn ich ein event verschicke (merke: reihenfolge der Daten muss mit der bei readStream uebereinstimmen + self.debug("SettingEvent:writeStream()") + if self.vehicle ~= nil then + self.debugVehicle(self.vehicle,"Vehicle setting") + streamWriteBool(streamId, true) + streamWriteInt32(streamId, NetworkUtil.getObjectId(self.vehicle)) + else + self.debug("Global setting") + streamWriteBool(streamId, false) + end + self.debug("Parent name: %s, Setting name: %s, value: %s, eventIx: %d",self.parentName, self.name, tostring(self.value),self.eventIx) + streamWriteString(streamId, self.parentName) + streamWriteString(streamId, self.name) + streamWriteUInt8(streamId,self.eventIx) + if self.writeFunc then + self.writeFunc(streamId, self.value) + end +end + +--- Runs the event on the receiving end of the event. +function SettingEvent:run(connection) -- wir fuehren das empfangene event aus + self.debug("SettingEvent:run()") + self.eventData.eventFunc(self.setting,self.value) + + --- If the receiver was the client make sure every clients gets also updated. + if not connection:getIsServer() then + self.debug("Send SettingEvent to clients") + g_server:broadcastEvent(SettingEvent:new(self.vehicle,self.setting,self.eventData,self.value), nil, connection, self.vehicle) + end; +end + +--- Sends an Event either: +--- - from the server to all clients or +--- - from the client to the server +---@param vehicle table +---@param setting Setting +---@param eventData table an event registers on the setting +---@param value any +function SettingEvent.sendEvent(vehicle,setting,eventData,value) + if g_server ~= nil then + SettingEvent.debug("Send SettingEvent to clients") + SettingEvent.debug("Setting name: %s",setting:getName()) + g_server:broadcastEvent(SettingEvent:new(vehicle,setting,eventData,value), nil, nil, vehicle) + else + SettingEvent.debug("Send SettingEvent to server") + SettingEvent.debug("Setting name: %s",setting:getName()) + g_client:getServerConnection():sendEvent(SettingEvent:new(vehicle,setting,eventData,value)) + end; +end + +function SettingEvent.debug(...) + courseplay.debugFormat(courseplay.DBG_MULTIPLAYER,...) +end + +function SettingEvent.debugVehicle(vehicle,...) + courseplay.debugVehicle(courseplay.DBG_MULTIPLAYER,vehicle,...) +end + +--- Gets all relevant values from the setting event to send the event. +---@param setting Setting +---@param eventData table +function SettingEvent.decodeEventData(setting,eventData) + local parentName = setting:getParentName() + local settingName = setting:getName() + local eventIx = eventData.ix + local writeFunc = eventData.writeFunc + return parentName,settingName,eventIx,writeFunc +end + +--- Gets the setting and event back from all received values. +---@param vehicle table +---@param parentName table Name of the setting container +---@param settingName string Name of the setting +---@param eventIx number Event number received +function SettingEvent.encodeEventData(vehicle,parentName,settingName,eventIx) + local setting + if vehicle then + setting = vehicle.cp[parentName][settingName] + else + setting = courseplay.globalSettings[parentName][settingName] + end + return setting,setting:getEvent(eventIx) +end diff --git a/Events/SettingsListEvent.lua b/Events/SettingsListEvent.lua deleted file mode 100644 index bf032853a..000000000 --- a/Events/SettingsListEvent.lua +++ /dev/null @@ -1,87 +0,0 @@ -SettingsListEvent = {}; -SettingsListEvent.TYPE_SETTING = 0 -SettingsListEvent.TYPE_GLOBAL = 1 -SettingsListEvent.TYPE_COURSEGENERATOR = 2 -local SettingsListEvent_mt = Class(SettingsListEvent, Event); - -InitEventClass(SettingsListEvent, "SettingsListEvent"); - -function SettingsListEvent:emptyNew() - local self = Event:new(SettingsListEvent_mt); - self.className = "SettingsListEvent"; - return self; -end - -function SettingsListEvent:new(vehicle,parentName, name, value) - courseplay:debug(string.format("SettingsListEvent:new(%s, %s, %s, %s)",nameNum(vehicle), tostring(name),tostring(parentName), tostring(value)), courseplay.DBG_MULTIPLAYER) - self.vehicle = nil - self.vehicle = vehicle; - self.parentName = parentName - self.name = name - self.value = value; - return self; -end - -function SettingsListEvent:readStream(streamId, connection) -- wird aufgerufen wenn mich ein Event erreicht - if streamReadBool(streamId) then - courseplay:debug("vehicle specific Setting",courseplay.DBG_MULTIPLAYER) - self.vehicle = NetworkUtil.getObject(streamReadInt32(streamId)) - else - courseplay:debug("global Setting",courseplay.DBG_MULTIPLAYER) - self.vehicle = nil - end - self.parentName = streamReadString(streamId) - self.name = streamReadString(streamId) - self.value = streamReadInt32(streamId) - - courseplay:debug("SettingsListEvent:readStream()",courseplay.DBG_MULTIPLAYER) - courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(nameNum(self.vehicle),tostring(self.parentName), tostring(self.name), tostring(self.value)), courseplay.DBG_MULTIPLAYER); - - self:run(connection); -end - -function SettingsListEvent:writeStream(streamId, connection) -- Wird aufgrufen wenn ich ein event verschicke (merke: reihenfolge der Daten muss mit der bei readStream uebereinstimmen - courseplay:debug("SettingsListEvent:writeStream()",courseplay.DBG_MULTIPLAYER) - courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(nameNum(self.vehicle),tostring(self.parentName), tostring(self.name), tostring(self.value)), courseplay.DBG_MULTIPLAYER); - if self.vehicle ~= nil then - courseplay:debug("vehicle specific Setting",courseplay.DBG_MULTIPLAYER) - streamWriteBool(streamId, true) - streamWriteInt32(streamId, NetworkUtil.getObjectId(self.vehicle)) - else - courseplay:debug("global Setting",courseplay.DBG_MULTIPLAYER) - streamWriteBool(streamId, false) - end - streamWriteString(streamId, self.parentName) - streamWriteString(streamId, self.name) - streamWriteInt32(streamId, self.value) -end - -function SettingsListEvent:run(connection) -- wir fuehren das empfangene event aus - courseplay:debug("SettingsListEvent:run()",courseplay.DBG_MULTIPLAYER) - courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(nameNum(self.vehicle),tostring(self.parentName), tostring(self.name), tostring(self.value)), courseplay.DBG_MULTIPLAYER); - - if self.vehicle then - courseplay:debug("vehicle specific Setting",courseplay.DBG_MULTIPLAYER) - self.vehicle.cp[self.parentName][self.name]:setFromNetwork(self.value) - else - courseplay:debug("global Setting",courseplay.DBG_MULTIPLAYER) - courseplay[self.parentName][self.name]:setFromNetwork(self.value) - end - if not connection:getIsServer() then - courseplay:debug("broadcast SettingsListEvent",courseplay.DBG_MULTIPLAYER) - g_server:broadcastEvent(SettingsListEvent:new(self.vehicle,self.parentName, self.name, self.value), nil, connection, self.vehicle); - end; -end - -function SettingsListEvent.sendEvent(vehicle,parentName, name, value) - if g_server ~= nil then - courseplay:debug("broadcast SettingsListEvent", courseplay.DBG_MULTIPLAYER) - courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(nameNum(vehicle), tostring(parentName), tostring(name), tostring(value)), courseplay.DBG_MULTIPLAYER); - g_server:broadcastEvent(SettingsListEvent:new(vehicle,parentName, name, value), nil, nil, vehicle); - else - courseplay:debug("send SettingsListEvent", courseplay.DBG_MULTIPLAYER) - courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(nameNum(vehicle), tostring(parentName),tostring(name), tostring(value)), courseplay.DBG_MULTIPLAYER); - g_client:getServerConnection():sendEvent(SettingsListEvent:new(vehicle,parentName, name, value)); - end; -end - diff --git a/Events/WorkWidthSettingEvent.lua b/Events/WorkWidthSettingEvent.lua deleted file mode 100644 index b185dd6f4..000000000 --- a/Events/WorkWidthSettingEvent.lua +++ /dev/null @@ -1,71 +0,0 @@ -WorkWidthSettingEvent = {}; -local WorkWidthSettingEvent_mt = Class(WorkWidthSettingEvent, Event); - -InitEventClass(WorkWidthSettingEvent, "WorkWidthSettingEvent"); - -function WorkWidthSettingEvent:emptyNew() - local self = Event:new(WorkWidthSettingEvent_mt); - self.className = "WorkWidthSettingEvent"; - return self; -end - ----@param value number (float) -function WorkWidthSettingEvent:new(vehicle, parentName, name, value) - courseplay:debugFormat(courseplay.DBG_MULTIPLAYER, - "WorkWidthSettingEvent:new(%s, %s, %s, %.1f)",nameNum(vehicle), name, parentName, value) - self.vehicle = vehicle - self.parentName = parentName - self.name = name - self.value = value - return self -end - --- deserialize received event -function WorkWidthSettingEvent:readStream(streamId, connection) - self.vehicle = NetworkUtil.getObject(streamReadInt32(streamId)) - self.parentName = streamReadString(streamId) - self.name = streamReadString(streamId) - self.value = streamReadFloat32(streamId) - - courseplay:debugFormat(courseplay.DBG_MULTIPLAYER, "WorkWidthSettingEvent:readStream(%s, %s, %s, %.1f)", - nameNum(self.vehicle), self.name, self.parentName, self.value) - - self:run(connection) -end - --- serialize event -function WorkWidthSettingEvent:writeStream(streamId, connection) - courseplay:debugFormat(courseplay.DBG_MULTIPLAYER, - "WorkWidthSettingEvent:writeStream(%s, %s, %s, %.1f)",nameNum(self.vehicle), self.name, self.parentName, self.value) - streamWriteInt32(streamId, NetworkUtil.getObjectId(self.vehicle)) - streamWriteString(streamId, self.parentName) - streamWriteString(streamId, self.name) - streamWriteFloat32(streamId, self.value) -end - --- process received event -function WorkWidthSettingEvent:run(connection) - courseplay:debugFormat(courseplay.DBG_MULTIPLAYER, - "WorkWidthSettingEvent:run(%s, %s, %s, %.1f)",nameNum(self.vehicle), self.name, self.parentName, self.value) - self.vehicle.cp[self.parentName][self.name]:setFromNetwork(self.value) - - if not connection:getIsServer() then - courseplay:debugFormat(courseplay.DBG_MULTIPLAYER, ' -> Broadcasting received event') - g_server:broadcastEvent(self, nil, connection, self.vehicle); - end; -end - -function WorkWidthSettingEvent.sendEvent(vehicle, parentName, name, value) - if g_server ~= nil then - courseplay:debugFormat(courseplay.DBG_MULTIPLAYER, - "WorkWidthSettingEvent:sendEvent broadcast to clients (%s, %s, %s, %.1f)",nameNum(vehicle), name, parentName, value) - - g_server:broadcastEvent(WorkWidthSettingEvent:new(vehicle,parentName, name, value), nil, nil, vehicle); - else - courseplay:debugFormat(courseplay.DBG_MULTIPLAYER, - "WorkWidthSettingEvent:sendEvent send to server (%s, %s, %s, %.1f)",nameNum(vehicle), name, parentName, value) - - g_client:getServerConnection():sendEvent(WorkWidthSettingEvent:new(vehicle,parentName, name, value)); - end; -end - diff --git a/Events/WorkingToolPositionsEvents.lua b/Events/WorkingToolPositionsEvents.lua deleted file mode 100644 index 6b174127f..000000000 --- a/Events/WorkingToolPositionsEvents.lua +++ /dev/null @@ -1,60 +0,0 @@ -WorkingToolPositionsEvents = {}; -local WorkingToolPositionsEvents_mt = Class(WorkingToolPositionsEvents, Event); - -InitEventClass(WorkingToolPositionsEvents, "WorkingToolPositionsEvents"); - -function WorkingToolPositionsEvents:emptyNew() - local self = Event:new(WorkingToolPositionsEvents_mt); - self.className = "WorkingToolPositionsEvents"; - return self; -end - -function WorkingToolPositionsEvents:new(vehicle,setting,eventType,position) - self.vehicle = vehicle; - self.setting = setting - self.eventType = eventType - self.position = position - return self; -end - -function WorkingToolPositionsEvents:readStream(streamId, connection) -- wird aufgerufen wenn mich ein Event erreicht - courseplay.debugVehicle(courseplay.DBG_MULTIPLAYER,self.vehicle,"readStream WorkingToolPositionsEvent") - self.vehicle = NetworkUtil.getObject(streamReadInt32(streamId)) - self.setting = streamReadString(streamId) - self.eventType = streamReadIntN(streamId,1) - self.position = streamReadUIntN(streamId,3) - self:run(connection); -end - -function WorkingToolPositionsEvents:writeStream(streamId, connection) -- Wird aufgrufen wenn ich ein event verschicke (merke: reihenfolge der Daten muss mit der bei readStream uebereinstimmen - courseplay.debugVehicle(courseplay.DBG_MULTIPLAYER,self.vehicle,"writeStream WorkingToolPositionsEvent") - streamWriteInt32(streamId, NetworkUtil.getObjectId(self.vehicle)) - streamWriteString(streamId,self.setting) - streamWriteIntN(streamId,self.eventType,1) - streamWriteUIntN(streamId,self.position,3) -end - -function WorkingToolPositionsEvents:run(connection) -- wir fuehren das empfangene event aus - courseplay.debugVehicle(courseplay.DBG_MULTIPLAYER,self.vehicle,"run WorkingToolPositionsEvent") - if self.eventType == WorkingToolPositionsSetting.NetworkTypes.SET_OR_CLEAR_POSITION then - self.vehicle.cp.settings[self.setting]:setOrClearPostion(self.position,true) - else - if not connection:getIsServer() then - self.vehicle.cp.settings[self.setting]:playPosition(self.position) - end - end - if not connection:getIsServer() then - courseplay.debugVehicle(courseplay.DBG_MULTIPLAYER,self.vehicle,"broadcast WorkingToolPositionsEvent") - g_server:broadcastEvent(WorkingToolPositionsEvents:new(self.vehicle,self.setting,self.eventType,self.position), nil, connection, self.vehicle); - end; -end - -function WorkingToolPositionsEvents.sendEvent(vehicle,setting,eventType,position) - if g_server ~= nil then - courseplay.debugVehicle(courseplay.DBG_MULTIPLAYER,vehicle,"broadcast WorkingToolPositionsEvent") - g_server:broadcastEvent(WorkingToolPositionsEvents:new(vehicle,setting,eventType,position), nil, nil, vehicle); - else - courseplay.debugVehicle(courseplay.DBG_MULTIPLAYER,vehicle,"send WorkingToolPositionsEvent") - g_client:getServerConnection():sendEvent(WorkingToolPositionsEvents:new(vehicle,setting,eventType,position)); - end; -end diff --git a/FieldworkAIDriver.lua b/FieldworkAIDriver.lua index e869dec26..e1a37bb4a 100644 --- a/FieldworkAIDriver.lua +++ b/FieldworkAIDriver.lua @@ -184,7 +184,7 @@ function FieldworkAIDriver:start(startingPoint) self.aiDriverOffsetX = 0 self.aiDriverOffsetZ = 0 - self.workWidth = courseplay:getWorkWidth(self.vehicle) + self.workWidth = self.courseGeneratorSettings.workWidth:getAutoWorkWidth() self.ppc:setNormalLookaheadDistance() self:setUpAndStart(startingPoint) @@ -667,7 +667,7 @@ function FieldworkAIDriver:onWaypointPassed(ix) local d, firstUpDownWpIx = self.course:getDistanceToFirstUpDownRowWaypoint(ix) self:debug('up/down rows start in %s meters.', tostring(d)) -- (no alignment if there is a turn generated here) - if d < self.vehicle.cp.turnDiameter * 2 and firstUpDownWpIx and not self.course:isTurnEndAtIx(firstUpDownWpIx) then + if d < self.settings.turnDiameter:get() * 2 and firstUpDownWpIx and not self.course:isTurnEndAtIx(firstUpDownWpIx) then self:debug('End connecting track, start working on up/down rows (waypoint %d) with alignment course if needed.', firstUpDownWpIx) self:startFieldworkWithAlignment(firstUpDownWpIx) end @@ -814,7 +814,7 @@ function FieldworkAIDriver:setUpCourses() -- apply the current tool offset to the fieldwork part (multitool offset is added by calculateOffsetCourse when needed) self.fieldworkCourse:setOffset(self.vehicle.cp.settings.toolOffsetX:get(), self.vehicle.cp.settings.toolOffsetZ:get()) -- TODO: consolidate the working width calculation and usage, this is currently an ugly mess - self.fieldworkCourse:setWorkWidth(self.vehicle.cp.courseWorkWidth or courseplay:getWorkWidth(self.vehicle)) + self.fieldworkCourse:setWorkWidth(self.vehicle.cp.courseWorkWidth or self.courseGeneratorSettings.workWidth:getAutoWorkWidth()) if self.vehicle.cp.courseGeneratorSettings.multiTools:get() > 1 then self:debug('Calculating offset course for position %d of %d', self.vehicle.cp.laneNumber, self.vehicle.cp.courseGeneratorSettings.multiTools:get()) diff --git a/FillableFieldworkAIDriver.lua b/FillableFieldworkAIDriver.lua index 726ae3cfd..7c3b5d509 100644 --- a/FillableFieldworkAIDriver.lua +++ b/FillableFieldworkAIDriver.lua @@ -294,13 +294,13 @@ end function FillableFieldworkAIDriver:getTurnEndForwardOffset() -- TODO: do other implements need this? if SpecializationUtil.hasSpecialization(Sprayer, self.vehicle.specializations) - and self.vehicle.cp.workWidth > self.vehicle.cp.turnDiameter then + and self.vehicle.cp.workWidth > self.settings.turnDiameter:get() then -- compensate for very wide implements like sprayer booms where the tip of the implement -- on the inner side of the turn may be very far forward of the vehicle's root and miss -- parts of the inside corner. - local forwardOffset = - (self.vehicle.cp.workWidth - self.vehicle.cp.turnDiameter) / 2.5 + local forwardOffset = - (self.vehicle.cp.workWidth - self.settings.turnDiameter:get()) / 2.5 self:debug('sprayer working width %.1f > turn diameter %.1f, applying forward offset %.1f to turn end', - self.vehicle.cp.workWidth, self.vehicle.cp.turnDiameter, forwardOffset) + self.vehicle.cp.workWidth, self.settings.turnDiameter:get(), forwardOffset) return forwardOffset else return 0 diff --git a/PlowAIDriver.lua b/PlowAIDriver.lua index f09f1dc95..b3c32fd7a 100644 --- a/PlowAIDriver.lua +++ b/PlowAIDriver.lua @@ -131,7 +131,7 @@ function PlowAIDriver:setOffsetX() -- TODO: Fix this offset dependency and copy paste local newToolOffsetX = -(leftMarkerDistance + rightMarkerDistance) / 2 -- set to the average of old and new to smooth a little bit to avoid oscillations - self.vehicle.cp.settings.toolOffsetX:set((self.vehicle.cp.settings.toolOffsetX:get() + newToolOffsetX) / 2) + self.vehicle.cp.settings.toolOffsetX:set((self.vehicle.cp.settings.toolOffsetX:get() + newToolOffsetX) / 2,true) self.vehicle.cp.totalOffsetX = self.vehicle.cp.settings.toolOffsetX:get() self:debug('%s: left = %.1f, right = %.1f, leftDx = %.1f, rightDx = %.1f, setting tool offsetX to %.2f (total offset %.2f)', nameNum(self.plow), leftMarkerDistance, rightMarkerDistance, leftDx, rightDx, self.vehicle.cp.settings.toolOffsetX:get(), self.vehicle.cp.totalOffsetX) diff --git a/PurePursuitController.lua b/PurePursuitController.lua index 86180822c..c3ef1b562 100644 --- a/PurePursuitController.lua +++ b/PurePursuitController.lua @@ -64,7 +64,7 @@ PurePursuitController.shortLookaheadDistance = 2.5 -- constructor function PurePursuitController:init(vehicle) - self.normalLookAheadDistance = math.min(vehicle.cp.turnDiameter / 2, 6) + self.normalLookAheadDistance = math.min(vehicle.cp.settings.turnDiameter:get() / 2, 6) self.shortLookaheadDistance = self.normalLookAheadDistance / 2 self.veryShortLookaheadDistance = 2 -- normal lookahead distance @@ -301,7 +301,7 @@ function PurePursuitController:havePassedWaypoint(wpNode) -- Also, when on the process of aligning to the course, like for example the vehicle just started -- driving towards the first waypoint, we have to make sure we actually get close to the waypoint -- (as we may already be in front of it), so try get within the turn diameter * 2. - if dz >= 0 and dFromNext < self.vehicle.cp.turnDiameter * 2 then + if dz >= 0 and dFromNext < self.vehicle.cp.settings.turnDiameter:get() * 2 then result = true end end diff --git a/VehicleConfigurations.lua b/VehicleConfigurations.lua index 737ebc57e..c831efe69 100644 --- a/VehicleConfigurations.lua +++ b/VehicleConfigurations.lua @@ -108,6 +108,10 @@ end --- @param attribute string configuration attribute to get --- @return any the value of the configuration attribute or nil if there's no custom config for it function VehicleConfigurations:get(object, attribute) + if not g_server then + courseplay.info("Error: VehicleConfigurations:get() %s",attribute) + return + end if object and object.configFileName then local vehicleXmlFileName = courseplay.utils:getFileNameFromPath(object.configFileName) if self.vehicleConfigurations[vehicleXmlFileName] then @@ -125,6 +129,10 @@ end --- @param attribute string configuration attribute to get --- @return any the value of the configuration attribute or nil if there's no custom config for it function VehicleConfigurations:getRecursively(object, attribute) + if not g_server then + courseplay.info("Error: VehicleConfigurations:getRecursively() %s",attribute) + return + end local value = self:get(object, attribute) if value then return value diff --git a/base.lua b/base.lua index 0118e6c7b..47b65bcdf 100644 --- a/base.lua +++ b/base.lua @@ -221,9 +221,6 @@ function courseplay:onLoad(savegame) self.cp.tipRefOffset = 0; self.cp.vehicleTurnRadius = courseplay:getVehicleTurnRadius(self); - self.cp.turnDiameter = self.cp.vehicleTurnRadius * 2; - self.cp.turnDiameterAuto = self.cp.vehicleTurnRadius * 2; - self.cp.turnDiameterAutoMode = true; --Offset @@ -446,17 +443,13 @@ function courseplay:onUpdate(dt) end if self.cp.postInitDone == nil then - --- Reset the current mode, as all implements are now attached. - --- If the vehicle is new, then cp.loadedMode is nil - if g_server then - self.cp.settings.driverMode:postInit() - end if self.cp.driver then ---Post init function, as not all giants variables are ---set correctly at the first courseplay:setAIDriver() call. self.cp.driver:postInit() - self.cp.postInitDone = true end + self.cp.settings.driverMode:postInit() + self.cp.postInitDone = true end -- we are in record mode @@ -685,8 +678,8 @@ function courseplay:onReadStream(streamId, connection) self.cp.courseGeneratorSettings:onReadStream(streamId) ------------------- - local copyCourseFromDriverId = streamDebugReadInt32(streamId) - if copyCourseFromDriverId then + local copyCourseFromDriverId = streamReadInt32(streamId) + if copyCourseFromDriverId and copyCourseFromDriverId~=-1 then self.cp.copyCourseFromDriver = NetworkUtil.getObject(copyCourseFromDriverId) end @@ -694,18 +687,18 @@ function courseplay:onReadStream(streamId, connection) -- kurs daten - local courses = streamDebugReadString(streamId) -- 60. - if courses ~= nil then + local courses = streamReadString(streamId) -- 60. + if courses ~= nil and courses~=-1 then self.cp.loadedCourses = StringUtil.splitString(",", courses); courseplay:reloadCourses(self, true) end - self.cp.numCourses = streamDebugReadInt32(streamId) + self.cp.numCourses = streamReadInt32(streamId) --print(string.format("%s:read: numCourses: %s loadedCourses: %s",tostring(self.name),tostring(self.cp.numCourses),tostring(#self.cp.loadedCourses))) if self.cp.numCourses > #self.cp.loadedCourses then self.Waypoints = {} - local wp_count = streamDebugReadInt32(streamId) + local wp_count = streamReadInt32(streamId) for w = 1, wp_count do table.insert(self.Waypoints, CourseEvent:readWaypoint(streamId)) end @@ -718,7 +711,7 @@ function courseplay:onReadStream(streamId, connection) -- SETUP 2D COURSE DRAW DATA self.cp.course2dUpdateDrawData = true; - local debugChannelsString = streamDebugReadString(streamId) + local debugChannelsString = streamReadString(streamId) for k,v in pairs(StringUtil.splitString(",", debugChannelsString)) do courseplay:toggleDebugChannel(self, k, v == 'true'); end; @@ -734,7 +727,7 @@ function courseplay:onReadStream(streamId, connection) --Make sure every vehicle has same AIDriver as the Server self.cp.driver:onReadStream(streamId) - + courseplay.debugFormat("driver mode: %s",self.cp.settings.driverMode:get()) courseplay:debug("id: "..tostring(self.id).." base: readStream end", courseplay.DBG_MULTIPLAYER) end @@ -752,23 +745,23 @@ function courseplay:onWriteStream(streamId, connection) self.cp.courseGeneratorSettings:onWriteStream(streamId) ------------- - local copyCourseFromDriverID; + local copyCourseFromDriverID = -1; if self.cp.copyCourseFromDriver ~= nil then copyCourseFromDriverID = NetworkUtil.getObjectId(self.cp.copyCourseFromDriver) end - streamDebugWriteInt32(streamId, copyCourseFromDriverID) + streamWriteInt32(streamId, copyCourseFromDriverID) - local loadedCourses; + local loadedCourses = ""; if #self.cp.loadedCourses then loadedCourses = table.concat(self.cp.loadedCourses, ",") end - streamDebugWriteString(streamId, loadedCourses) -- 60. - streamDebugWriteInt32(streamId, self.cp.numCourses) + streamWriteString(streamId, loadedCourses) + streamWriteInt32(streamId, self.cp.numCourses) --print(string.format("%s:write: numCourses: %s loadedCourses: %s",tostring(self.name),tostring(self.cp.numCourses),tostring(#self.cp.loadedCourses))) if self.cp.numCourses > #self.cp.loadedCourses then courseplay:debug("id: "..tostring(NetworkUtil.getObjectId(self)).." sync temp course", courseplay.DBG_MULTIPLAYER) - streamDebugWriteInt32(streamId, #(self.Waypoints)) + streamWriteInt32(streamId, #(self.Waypoints)) for w = 1, #(self.Waypoints) do --print("writing point "..tostring(w)) CourseEvent:writeWaypoint(streamId, self.Waypoints[w]) @@ -776,7 +769,7 @@ function courseplay:onWriteStream(streamId, connection) end local debugChannelsString = table.concat(table.map(courseplay.debugChannels, tostring), ","); - streamDebugWriteString(streamId, debugChannelsString) + streamWriteString(streamId, debugChannelsString) if self.cp.timeRemaining then streamWriteBool(streamId,true) @@ -793,7 +786,7 @@ function courseplay:onWriteStream(streamId, connection) end self.cp.driver:onWriteStream(streamId) - + courseplay.debugFormat("driver mode: %s",self.cp.settings.driverMode:get()) courseplay:debug("id: "..tostring(NetworkUtil.getObjectId(self)).." base: write stream end", courseplay.DBG_MULTIPLAYER) end @@ -801,11 +794,9 @@ end function courseplay:onReadUpdateStream(streamId, timestamp, connection) if connection:getIsServer() then - if self.cp.driver ~= nil then - self.cp.driver:readUpdateStream(streamId, timestamp, connection) - end --only sync while cp is drivin! if streamReadBool(streamId) then + self.cp.driver:readUpdateStream(streamId, timestamp, connection) if streamReadBool(streamId) then self.cp.waypointIndex = streamReadInt32(streamId) else @@ -839,10 +830,9 @@ end function courseplay:onWriteUpdateStream(streamId, connection, dirtyMask) if not connection:getIsServer() then - if self.cp.driver ~= nil then + streamWriteBool(streamId, self:getIsCourseplayDriving() or false) + if self:getIsCourseplayDriving() then self.cp.driver:writeUpdateStream(streamId, connection, dirtyMask) - end - if streamWriteBool(streamId, self:getIsCourseplayDriving() or false) then if self.cp.waypointIndex then streamWriteBool(streamId,true) streamWriteInt32(streamId,self.cp.waypointIndex) @@ -904,12 +894,6 @@ function courseplay:loadVehicleCPSettings(xmlFile, key, resetVehicles) curKey = key .. '.courseplay.HUD'; self.cp.hud.show = Utils.getNoNil( getXMLBool(xmlFile, curKey .. '#showHud'), false); - - - curKey = key .. '.courseplay.driving'; - self.cp.turnDiameter = Utils.getNoNil( getXMLInt(xmlFile, curKey .. '#turnDiameter'), self.cp.vehicleTurnRadius * 2); - self.cp.turnDiameterAutoMode = Utils.getNoNil( getXMLBool(xmlFile, curKey .. '#turnDiameterAutoMode'), true); - -- MODES 4 / 6 curKey = key .. '.courseplay.fieldWork'; @@ -966,11 +950,6 @@ function courseplay:saveToXMLFile(xmlFile, key, usedModNames) - - --driving settings - setXMLInt(xmlFile, newKey..".driving #turnDiameter", self.cp.turnDiameter) - setXMLBool(xmlFile, newKey..".driving #turnDiameterAutoMode", self.cp.turnDiameterAutoMode) - --field work settings local offsetData = string.format('%.1f;%.1f;%.1f;%s;%.1f;%.1f;%d', self.cp.laneOffset, 0, 0, 0, 0, 0, self.cp.laneNumber); setXMLString(xmlFile, newKey..".fieldWork #workWidth", string.format("%.1f",self.cp.workWidth)) diff --git a/course-generator/CourseGeneratorSettings.lua b/course-generator/CourseGeneratorSettings.lua index 9d4c547f1..aceb153bc 100644 --- a/course-generator/CourseGeneratorSettings.lua +++ b/course-generator/CourseGeneratorSettings.lua @@ -119,6 +119,7 @@ WorkWidthSetting.Increment = 0.1 function WorkWidthSetting:init(vehicle) SettingList.init(self, 'workWidth', 'COURSEPLAY_WORK_WIDTH', 'COURSEPLAY_WORK_WIDTH', vehicle) self.value = FloatSetting('workWidth', 'COURSEPLAY_WORK_WIDTH', 'COURSEPLAY_WORK_WIDTH', vehicle, 0) + self.automaticValue = FloatSetting('automaticWorkWidth',nil,nil,vehicle,0) self.minWidth, self.maxWidth = 1, 50 -- do not attempt to send an event from the constructor as at that point, the vehicle is not completely ready -- and parentName is not set. @@ -126,6 +127,11 @@ function WorkWidthSetting:init(vehicle) -- TODO: add parentName to the constructor of the settings instead of the explicit setter. self:setToDefault(true) self:refresh() + self.WORK_WIDTH_EVENT = self:registerFloatEvent(self.setWorkWidthFromNetwork) + self.AUTO_WORK_WIDTH_EVENT = self:registerFloatEvent(self.setAutoWorkWidthFromNetwork) + if g_server then + self:updateAutoWorkWidth() + end end function WorkWidthSetting:loadFromXml(xml, parentKey) @@ -139,10 +145,12 @@ end function WorkWidthSetting:onWriteStream(stream) self.value:onWriteStream(stream) + self.automaticValue:onWriteStream(stream) end function WorkWidthSetting:onReadStream(stream) self.value:onReadStream(stream) + self.automaticValue:onReadStream(stream) self:updateGuiElement() end @@ -181,27 +189,36 @@ function WorkWidthSetting:setFromGuiElement() end function WorkWidthSetting:setToDefault(noEventSend) - local autoWidth = courseplay:getWorkWidth(self.vehicle) + local autoWidth = self:getAutoWorkWidth() if autoWidth > 0 then - self:set(courseplay:getWorkWidth(self.vehicle), noEventSend) + self:set(autoWidth, noEventSend) end end function WorkWidthSetting:set(value, noEventSend) self.value:set(value, noEventSend) - if not noEventSend then - self:sendEvent() + if noEventSend == nil or noEventSend == false then + self:sendWorkWidthEvent(value) end self:updateGuiElement() end -- override SettingList sendEvent() for setting the float value from the list -function WorkWidthSetting:sendEvent() - WorkWidthSettingEvent.sendEvent(self.vehicle, self.parentName, self.name, self.value:get()) +function WorkWidthSetting:sendWorkWidthEvent(value) + self:raiseEvent(self.WORK_WIDTH_EVENT,value) +end + +-- override SettingList sendEvent() for setting the float auto work width +function WorkWidthSetting:sendAutoWorkWidthEvent(value) + self:raiseEvent(self.AUTO_WORK_WIDTH_EVENT,value) +end + +function WorkWidthSetting:setWorkWidthFromNetwork(value) + self.value:set(value,true) end -function WorkWidthSetting:setFromNetwork(value) - self.value:set(value, true) +function WorkWidthSetting:setAutoWorkWidthFromNetwork(value) + self.automaticValue:set(value,true) end function WorkWidthSetting:setNext() @@ -212,6 +229,19 @@ function WorkWidthSetting:setPrevious() self:set(math.max(self.value:get() - WorkWidthSetting.Increment, self.minWidth)) end +--- This is needed as the client can't retrieve it directly, +--- so we update it on a attach/detach of an implement and +--- send the changed value with an event to the client. +function WorkWidthSetting:updateAutoWorkWidth() + local value = courseplay:getWorkWidth(self.vehicle) or 0 + self.automaticValue:set(value,true) + self:sendAutoWorkWidthEvent(value) +end + +function WorkWidthSetting:getAutoWorkWidth() + return self.automaticValue:get() +end + --- Course gen center mode setting ---@class CenterModeSetting : SettingList CenterModeSetting = CpObject(SettingList) diff --git a/course-generator/cp.lua b/course-generator/cp.lua index 5f3ac3c2d..8294e3893 100644 --- a/course-generator/cp.lua +++ b/course-generator/cp.lua @@ -156,7 +156,7 @@ function courseGenerator.generate(vehicle) -- tool causing the innermost tool on the headland -- turn tighter than possible -- Using vehicle.cp.turnDiameter as this is updated when the user changes the value - local turnRadiusAdjustedForMultiTool = vehicle.cp.turnDiameter / 2 + + local turnRadiusAdjustedForMultiTool = vehicle.cp.settings.turnDiameter:get() / 2 + vehicle.cp.courseGeneratorSettings.workWidth:get() * (vehicle.cp.courseGeneratorSettings.multiTools:get() - 1) / 2 local status, ok = xpcall(generateCourseForField, function(err) diff --git a/course_management.lua b/course_management.lua index ebcac25bd..273fd607c 100644 --- a/course_management.lua +++ b/course_management.lua @@ -307,7 +307,6 @@ function courseplay:loadCourse(vehicle, id, useRealId, addCourseAtEnd) -- fn is courseplay.hud:setReloadPageOrder(vehicle, vehicle.cp.hud.currentPage, true) if CpManager.isMP and g_server ~= nil then - -- CourseplayEvent.sendEvent(vehicle, "setVehicleWaypoints", vehicle.Waypoints, courseplay.isClient); CourseEvent.sendEvent(vehicle,vehicle.Waypoints) end end diff --git a/courseplay.lua b/courseplay.lua index 9ac30bd8b..ca5f847bb 100644 --- a/courseplay.lua +++ b/courseplay.lua @@ -138,18 +138,15 @@ local function initialize() 'gui/AdvancedSettingsScreen', 'gui/GlobalSettingsPage', 'gui/VehicleSettingsPage', + 'Events/SettingEvent', 'Events/StartStopEvent', 'Events/UnloaderEvents', 'Events/SiloSelectedFillTypeEvent', 'Events/StartStopWorkEvent', - 'Events/SettingsListEvent', - 'Events/GlobalSettingsEvent', 'Events/AssignedCombinesEvents', 'Events/CourseEvent', 'Events/InfoTextEvent', - 'Events/WorkingToolPositionsEvents', 'Events/CommandEvents', - 'Events/WorkWidthSettingEvent', 'Generic/LinkedList' }; @@ -239,24 +236,21 @@ local function setGlobalData() courseplay.multiplayerSyncTable = { - [1]={name='self.cp.turnDiameterAuto',dataFormat='Float'}, - [2]={name='self.cp.canDrive',dataFormat='Bool'}, - [3]={name='self.cp.drivingDirReverse',dataFormat='Bool'}, - [4]={name='self.cp.fieldEdge.customField.isCreated',dataFormat='Bool'}, - [5]={name='self.cp.fieldEdge.customField.fieldNum',dataFormat='Int'}, - [6]={name='self.cp.fieldEdge.customField.selectedFieldNumExists',dataFormat='Bool'}, - [7]={name='self.cp.fieldEdge.selectedField.fieldNum',dataFormat='Int'}, - [8]={name='self.cp.isDriving',dataFormat='Bool'}, - [9]={name='self.cp.hud.openWithMouse',dataFormat='Bool'}, - [10]={name='self.cp.workWidth',dataFormat='Float'}, - [11]={name='self.cp.turnDiameterAutoMode',dataFormat='Bool'}, - [12]={name='self.cp.turnDiameter',dataFormat='Float'}, - [13]={name='self.cp.coursePlayerNum',dataFormat='Int'}, --?? - [14]={name='self.cp.laneOffset',dataFormat='Float'}, - [15]={name='self.cp.hud.currentPage',dataFormat='Int'}, - [16]={name='self.cp.waypointIndex',dataFormat='Int'}, - [17]={name='self.cp.isRecording',dataFormat='Bool'}, - [18]={name='self.cp.recordingIsPaused',dataFormat='Bool'}, + [1]={name='self.cp.canDrive',dataFormat='Bool'}, + [2]={name='self.cp.drivingDirReverse',dataFormat='Bool'}, + [3]={name='self.cp.fieldEdge.customField.isCreated',dataFormat='Bool'}, + [4]={name='self.cp.fieldEdge.customField.fieldNum',dataFormat='Int'}, + [5]={name='self.cp.fieldEdge.customField.selectedFieldNumExists',dataFormat='Bool'}, + [6]={name='self.cp.fieldEdge.selectedField.fieldNum',dataFormat='Int'}, + [7]={name='self.cp.isDriving',dataFormat='Bool'}, + [8]={name='self.cp.hud.openWithMouse',dataFormat='Bool'}, + [9]={name='self.cp.workWidth',dataFormat='Float'}, + [10]={name='self.cp.coursePlayerNum',dataFormat='Int'}, --?? + [11]={name='self.cp.laneOffset',dataFormat='Float'}, + [12]={name='self.cp.hud.currentPage',dataFormat='Int'}, + [13]={name='self.cp.waypointIndex',dataFormat='Int'}, + [14]={name='self.cp.isRecording',dataFormat='Bool'}, + [15]={name='self.cp.recordingIsPaused',dataFormat='Bool'}, } courseplay.globalSettings = SettingsContainer.createGlobalSettings() diff --git a/courseplay_event.lua b/courseplay_event.lua index a41ed5ba9..a97df162a 100644 --- a/courseplay_event.lua +++ b/courseplay_event.lua @@ -70,8 +70,8 @@ function CourseplayEvent:writeStream(streamId, connection) -- Wird aufgrufen we courseplay:debugVehicle(courseplay.DBG_MULTIPLAYER,self.vehicle," writeStream:") courseplay:debugVehicle(courseplay.DBG_MULTIPLAYER,self.vehicle," messageNumber: %s, functionCall: %s, value: %s, page: %s, type: %s ",tostring(messageNumber), tostring(self.func), tostring(self.value),tostring(self.page), tostring(self.type)) NetworkUtil.writeNodeObject(streamId, self.vehicle); - streamWriteFloat32(streamId, self.messageNumber); - streamWriteString(streamId, self.func); + streamDebugWriteFloat32(streamId, self.messageNumber); + streamDebugWriteString(streamId, self.func); if self.page == "global" then self.page = 999 elseif self.page == true then @@ -81,21 +81,21 @@ function CourseplayEvent:writeStream(streamId, connection) -- Wird aufgrufen we elseif self.page == nil then self.page = 996 end - streamWriteInt32(streamId, self.page); - streamWriteString(streamId, self.type); + streamDebugWriteInt32(streamId, self.page); + streamDebugWriteString(streamId, self.type); if self.type == "boolean" then - streamWriteBool(streamId, self.value); + streamDebugWriteBool(streamId, self.value); elseif self.type == "string" then - streamWriteString(streamId, self.value); + streamDebugWriteString(streamId, self.value); elseif self.type == "nil" then - streamWriteString(streamId, "nil"); + streamDebugWriteString(streamId, "nil"); elseif self.type == "waypointList" then - streamWriteInt32(streamId, #(self.value)) + streamDebugWriteInt32(streamId, #(self.value)) for w = 1, #(self.value) do CoursePlayNetworkHelper:writeWaypoint(streamId, self.value[w]) end else - streamWriteFloat32(streamId, self.value); + streamDebugWriteFloat32(streamId, self.value); end end @@ -123,15 +123,6 @@ function CourseplayEvent.sendEvent(vehicle, func, value, noEventSend, page) -- h end; end -function courseplay:checkForChangeAndBroadcast(self, stringName, variable , variableMemory) - if variable ~= variableMemory then - courseplay:debugVehicle(courseplay.DBG_MULTIPLAYER,vehicle,"checkForChangeAndBroadcast") - CourseplayEvent.sendEvent(self, stringName, variable) - variableMemory = variable - end - return variableMemory - -end @@ -163,6 +154,7 @@ end CourseplayJoinFixEvent = {}; CourseplayJoinFixEvent_mt = Class(CourseplayJoinFixEvent, Event); +CourseplayJoinFixEvent.mpDebugActive = true InitEventClass(CourseplayJoinFixEvent, "CourseplayJoinFixEvent"); @@ -181,7 +173,6 @@ function CourseplayJoinFixEvent:writeStream(streamId, connection) if not connection:getIsServer() then courseplay.globalSettings:onWriteStream(streamId) - --transfer courses local course_count = 0 for _,_ in pairs(g_currentMission.cp_courses) do @@ -191,13 +182,20 @@ function CourseplayJoinFixEvent:writeStream(streamId, connection) streamDebugWriteInt32(streamId, course_count) for id, course in pairs(g_currentMission.cp_courses) do streamDebugWriteString(streamId, course.name) + self:debugWrite(course.name,"course name") streamDebugWriteString(streamId, course.uid) + self:debugWrite(course.uid,"course uid") streamDebugWriteString(streamId, course.type) + self:debugWrite(course.type,"course type") streamDebugWriteInt32(streamId, course.id) + self:debugWrite(course.id,"course id") streamDebugWriteInt32(streamId, course.parent) + self:debugWrite(course.parent,"course parent") streamDebugWriteInt32(streamId, course.multiTools) + self:debugWrite(course.multiTools,"course multiTools") if course.waypoints then streamDebugWriteInt32(streamId, #(course.waypoints)) + self:debugWrite(#(course.waypoints),"course numWaypoints") for w = 1, #(course.waypoints) do CourseEvent:writeWaypoint(streamId, course.waypoints[w]) end @@ -205,7 +203,7 @@ function CourseplayJoinFixEvent:writeStream(streamId, connection) streamDebugWriteInt32(streamId, -1) end end - + self:debug("Stream write folders") local folderCount = 0 for _,_ in pairs(g_currentMission.cp_folders) do folderCount = folderCount + 1 @@ -214,14 +212,20 @@ function CourseplayJoinFixEvent:writeStream(streamId, connection) print(string.format("\t### CourseplayMultiplayer: writing %d folders ", folderCount )) for id, folder in pairs(g_currentMission.cp_folders) do streamDebugWriteString(streamId, folder.name) + self:debugWrite(folder.name,"folder name") streamDebugWriteString(streamId, folder.uid) + self:debugWrite(folder.uid,"folder uid") streamDebugWriteString(streamId, folder.type) + self:debugWrite(folder.type,"folder type") streamDebugWriteInt32(streamId, folder.id) + self:debugWrite(folder.id,"folder id") streamDebugWriteInt32(streamId, folder.parent) + self:debugWrite(folder.parent,"folder parent") streamDebugWriteBool(streamId, folder.virtual) + self:debugWrite(folder.virtual,"folder virtual") streamDebugWriteBool(streamId, folder.autodrive) - end - + self:debugWrite(folder.autodrive,"folder autodrive") + end local fieldsCount = 0 for _, field in pairs(courseplay.fields.fieldData) do if field.isCustom then @@ -230,21 +234,33 @@ function CourseplayJoinFixEvent:writeStream(streamId, connection) end streamDebugWriteInt32(streamId, fieldsCount) print(string.format("\t### CourseplayMultiplayer: writing %d custom fields ", fieldsCount)) - for id, course in pairs(courseplay.fields.fieldData) do - if course.isCustom then - streamDebugWriteString(streamId, course.name) - streamDebugWriteInt32(streamId, course.numPoints) - streamDebugWriteBool(streamId, course.isCustom) - streamDebugWriteInt32(streamId, course.fieldNum) - streamDebugWriteInt32(streamId, course.dimensions.minX) - streamDebugWriteInt32(streamId, course.dimensions.maxX) - streamDebugWriteInt32(streamId, course.dimensions.minZ) - streamDebugWriteInt32(streamId, course.dimensions.maxZ) - streamDebugWriteInt32(streamId, #(course.points)) - for p = 1, #(course.points) do - streamDebugWriteFloat32(streamId, course.points[p].cx) - streamDebugWriteFloat32(streamId, course.points[p].cy) - streamDebugWriteFloat32(streamId, course.points[p].cz) + for id, field in pairs(courseplay.fields.fieldData) do + if field.isCustom then + streamDebugWriteString(streamId, field.name) + self:debugWrite(field.name,"field name") + streamDebugWriteInt32(streamId, field.numPoints) + self:debugWrite(field.numPoints,"field numPoints") + streamDebugWriteBool(streamId, field.isCustom) + self:debugWrite(field.isCustom,"field isCustom") + streamDebugWriteInt32(streamId, field.fieldNum) + self:debugWrite(field.fieldNum,"field fieldNum") + streamDebugWriteInt32(streamId, field.dimensions.minX) + self:debugWrite(field.dimensions.min,"field minX") + streamDebugWriteInt32(streamId, field.dimensions.maxX) + self:debugWrite(field.dimensions.maxX,"field maxX") + streamDebugWriteInt32(streamId, field.dimensions.minZ) + self:debugWrite(field.dimensions.minZ,"field minZ") + streamDebugWriteInt32(streamId, field.dimensions.maxZ) + self:debugWrite(field.dimensions.maxZ,"field maxZ") + streamDebugWriteInt32(streamId, #(field.points)) + self:debugWrite(field.points,"field points") + for p = 1, #(field.points) do + streamDebugWriteFloat32(streamId, field.points[p].cx) + self:debugWrite(field.points[p].cx,"field cx") + streamDebugWriteFloat32(streamId, field.points[p].cy) + self:debugWrite(field.points[p].cy,"field cy") + streamDebugWriteFloat32(streamId, field.points[p].cz) + self:debugWrite(field.points[p].cz,"field cz") end end end @@ -254,19 +270,25 @@ end function CourseplayJoinFixEvent:readStream(streamId, connection) if connection:getIsServer() then courseplay.globalSettings:onReadStream(streamId) - - local course_count = streamDebugReadInt32(streamId) + local course_count = streamReadInt32(streamId) print(string.format("\t### CourseplayMultiplayer: reading %d couses ", course_count )) g_currentMission.cp_courses = {} for i = 1, course_count do --courseplay:debug("got course", courseplay.DBG_COURSES); - local course_name = streamDebugReadString(streamId) - local courseUid = streamDebugReadString(streamId) - local courseType = streamDebugReadString(streamId) - local course_id = streamDebugReadInt32(streamId) - local courseParent = streamDebugReadInt32(streamId) - local courseMultiTools = streamDebugReadInt32(streamId) - local wp_count = streamDebugReadInt32(streamId) + local course_name = streamReadString(streamId) + self:debugRead(course_name,"course name") + local courseUid = streamReadString(streamId) + self:debugRead(courseUid,"course uid") + local courseType = streamReadString(streamId) + self:debugRead(courseType,"course type") + local course_id = streamReadInt32(streamId) + self:debugRead(course_id,"course id") + local courseParent = streamReadInt32(streamId) + self:debugRead(courseParent,"course parent") + local courseMultiTools = streamReadInt32(streamId) + self:debugRead(courseMultiTools,"course multi tools") + local wp_count = streamReadInt32(streamId) + self:debugRead(wp_count,"course waypoint amount") local waypoints = {} if wp_count >= 0 then for w = 1, wp_count do @@ -280,41 +302,58 @@ function CourseplayJoinFixEvent:readStream(streamId, connection) g_currentMission.cp_courses[course_id] = course g_currentMission.cp_sorted = courseplay.courses:sort() end - - local folderCount = streamDebugReadInt32(streamId) + local folderCount = streamReadInt32(streamId) print(string.format("\t### CourseplayMultiplayer: reading %d folders ", folderCount )) g_currentMission.cp_folders = {} for i = 1, folderCount do - local folderName = streamDebugReadString(streamId) - local folderUid = streamDebugReadString(streamId) - local folderType = streamDebugReadString(streamId) - local folderId = streamDebugReadInt32(streamId) - local folderParent = streamDebugReadInt32(streamId) - local folderVirtual = streamDebugReadBool(streamId) - local folderAutoDrive = streamDebugReadBool(streamId) + local folderName = streamReadString(streamId) + self:debugRead(folderName,"folder name") + local folderUid = streamReadString(streamId) + self:debugRead(folderUid,"folder uid") + local folderType = streamReadString(streamId) + self:debugRead(folderType,"folder type") + local folderId = streamReadInt32(streamId) + self:debugRead(folderId,"folder id") + local folderParent = streamReadInt32(streamId) + self:debugRead(folderParent,"folder parent") + local folderVirtual = streamReadBool(streamId) + self:debugRead(folderVirtual,"folder virtual") + local folderAutoDrive = streamReadBool(streamId) + self:debugRead(folderAutoDrive,"folder is auto drive") local folder = { id = folderId, uid = folderUid, type = folderType, name = folderName, nameClean = courseplay:normalizeUTF8(folderName), parent = folderParent, virtual = folderVirtual, autodrive = folderAutoDrive } g_currentMission.cp_folders[folderId] = folder g_currentMission.cp_sorted = courseplay.courses:sort(g_currentMission.cp_courses, g_currentMission.cp_folders, 0, 0) end - - local fieldsCount = streamDebugReadInt32(streamId) + local fieldsCount = streamReadInt32(streamId) print(string.format("\t### CourseplayMultiplayer: reading %d custom fields ", fieldsCount)) courseplay.fields.fieldData = {} for i = 1, fieldsCount do - local name = streamDebugReadString(streamId) - local numPoints = streamDebugReadInt32(streamId) - local isCustom = streamDebugReadBool(streamId) - local fieldNum = streamDebugReadInt32(streamId) - local minX = streamDebugReadInt32(streamId) - local maxX = streamDebugReadInt32(streamId) - local minZ = streamDebugReadInt32(streamId) - local maxZ = streamDebugReadInt32(streamId) - local ammountPoints = streamDebugReadInt32(streamId) + local name = streamReadString(streamId) + self:debugRead(name,"field name") + local numPoints = streamReadInt32(streamId) + self:debugRead(numPoints,"field numPoints") + local isCustom = streamReadBool(streamId) + self:debugRead(isCustom,"field isCustom") + local fieldNum = streamReadInt32(streamId) + self:debugRead(fieldNum,"field fieldNum") + local minX = streamReadInt32(streamId) + self:debugRead(minX,"field minX") + local maxX = streamReadInt32(streamId) + self:debugRead(maxX,"field maxX") + local minZ = streamReadInt32(streamId) + self:debugRead(minZ,"field minZ") + local maxZ = streamReadInt32(streamId) + self:debugRead(maxZ,"field maxZ") + local ammountPoints = streamReadInt32(streamId) + self:debugRead(ammountPoints,"field numPoints") local waypoints = {} for w = 1, ammountPoints do - local cx = streamDebugReadFloat32(streamId) - local cy = streamDebugReadFloat32(streamId) - local cz = streamDebugReadFloat32(streamId) + local cx = streamReadFloat32(streamId) + self:debugRead(cx,"field cx") + local cy = streamReadFloat32(streamId) + self:debugRead(cy,"field cy") + local cz = streamReadFloat32(streamId) + self:debugRead(cz,"field cz") local wp = { cx = cx, cy = cy, cz = cz} table.insert(waypoints, wp) end @@ -325,6 +364,22 @@ function CourseplayJoinFixEvent:readStream(streamId, connection) end; end +function CourseplayJoinFixEvent:debug(str,...) +--- if courseplay.debugChannels[courseplay.DBG_MULTIPLAYER] then +--- courseplay.debugFormat(courseplay.DBG_MULTIPLAYER,...) +--- end + if self.mpDebugActive then + print(string.format(str,...)) + end +end + +function CourseplayJoinFixEvent:debugWrite(value,valueName) + self:debug("Stream write, %s: %s ",valueName,tostring(value)) +end + +function CourseplayJoinFixEvent:debugRead(value,valueName) + self:debug("Stream read, %s: %s ",valueName,tostring(value)) +end function CourseplayJoinFixEvent:run(connection) --courseplay:debug("CourseplayJoinFixEvent Run function should never be called", courseplay.DBG_COURSES); end; diff --git a/debug.lua b/debug.lua index 6d4e47111..32b9c7698 100644 --- a/debug.lua +++ b/debug.lua @@ -1,5 +1,7 @@ courseplay = courseplay or {} +--- TODO: create a xml file for the debug channel setup and additional developer settings. + -- Debug channels. The numbers represent the channel numbers on the HUD courseplay.DBG_MODE_1 = 1 courseplay.DBG_MODE_2 = 2 @@ -56,6 +58,7 @@ function CpManager:setUpDebugChannels() end; end; + -- DEBUG CHANNELS courseplay.numAvailableDebugChannels = 24; courseplay.numDebugChannels = 24; @@ -344,7 +347,7 @@ stream_debug_counter = 0; function streamDebugWriteFloat32(streamId, value) value = Utils.getNoNil(value, 0.0) stream_debug_counter = stream_debug_counter + 1 - courseplay:debug(string.format("%d: writing float: %f",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) +--- courseplay:debug(string.format("%d: writing float: %f",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) streamWriteFloat32(streamId, value) end @@ -357,21 +360,21 @@ function streamDebugWriteBool(streamId, value) end stream_debug_counter = stream_debug_counter + 1 - courseplay:debug(string.format("%d: writing bool: %s",stream_debug_counter, tostring(value) ),courseplay.DBG_MULTIPLAYER) +--- courseplay:debug(string.format("%d: writing bool: %s",stream_debug_counter, tostring(value) ),courseplay.DBG_MULTIPLAYER) streamWriteBool(streamId, value) end function streamDebugWriteInt32(streamId, value) value = Utils.getNoNil(value, 0) stream_debug_counter = stream_debug_counter + 1 - courseplay:debug(string.format("%d: writing int: %d",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) +--- courseplay:debug(string.format("%d: writing int: %d",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) streamWriteInt32(streamId, value) end function streamDebugWriteString(streamId, value) value = Utils.getNoNil(value, "") stream_debug_counter = stream_debug_counter + 1 - courseplay:debug(string.format("%d: writing string: %s",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) +--- courseplay:debug(string.format("%d: writing string: %s",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) streamWriteString(streamId, value) end @@ -379,7 +382,7 @@ end function streamDebugReadFloat32(streamId) stream_debug_counter = stream_debug_counter + 1 local value = streamReadFloat32(streamId) - courseplay:debug(string.format("%d: reading float: %f",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) +--- courseplay:debug(string.format("%d: reading float: %f",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) return value end @@ -387,21 +390,21 @@ end function streamDebugReadInt32(streamId) stream_debug_counter = stream_debug_counter + 1 local value = streamReadInt32(streamId) - courseplay:debug(string.format("%d: reading int: %d",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) +--- courseplay:debug(string.format("%d: reading int: %d",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) return value end function streamDebugReadBool(streamId) stream_debug_counter = stream_debug_counter + 1 local value = streamReadBool(streamId) - courseplay:debug(string.format("%d: reading bool: %s",stream_debug_counter, tostring(value)),courseplay.DBG_MULTIPLAYER) +--- courseplay:debug(string.format("%d: reading bool: %s",stream_debug_counter, tostring(value)),courseplay.DBG_MULTIPLAYER) return value end function streamDebugReadString(streamId) stream_debug_counter = stream_debug_counter + 1 local value = streamReadString(streamId) - courseplay:debug(string.format("%d: reading string: %s",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) +--- courseplay:debug(string.format("%d: reading string: %s",stream_debug_counter, value ),courseplay.DBG_MULTIPLAYER) return value end diff --git a/fields.lua b/fields.lua index 83057c2ea..b3dbd1c09 100644 --- a/fields.lua +++ b/fields.lua @@ -49,9 +49,20 @@ function courseplay.fields:setAllFieldEdges() local fieldDef = courseplay.fields.fieldDefinitionBase[self.curFieldScanIndex]; if fieldDef ~= nil then - if not self.onlyScanOwnedFields or (self.onlyScanOwnedFields and (fieldDef.farmland.isOwned or fieldDef.currentMission)) then --TODO: Check, whether I'm the owner - --if not self.onlyScanOwnedFields or (self.onlyScanOwnedFields and fieldDef.ownedByPlayer) then - local fieldNum = fieldDef.fieldId; + local fieldNum = fieldDef.fieldId; + local missionActive = false + --- Make sure active mission fields get also scanned. + if g_missionManager:getIsAnyMissionActive() then + local activeMissions = g_missionManager:getActiveMissions() + for _,m in pairs(activeMissions) do + missionActive = m.field and m.field.fieldId == fieldNum + if missionActive then + break + end + end + end + + if not self.onlyScanOwnedFields or (self.onlyScanOwnedFields and (fieldDef.farmland.isOwned or missionActive)) then if self.fieldData[fieldNum] == nil then local initObject = fieldDef.nameIndicator; local x,_,z = getWorldTranslation(initObject); @@ -417,7 +428,6 @@ function courseplay.fields.addContractField(self) -- scan field when we take a c end; AbstractFieldMission.addToMissionMap = Utils.appendedFunction(AbstractFieldMission.addToMissionMap, courseplay.fields.addContractField); - function courseplay.fields.removeContractField(self, success) -- scan field when we complete a contract -- print(string.format('buyField(fieldDef, isOwned) [fieldNumber %s]', tostring(fieldDef.fieldNumber))); if g_currentMission.time > 0 and courseplay.globalSettings.autoFieldScan:is(true) and courseplay.fields.onlyScanOwnedFields and courseplay.fields.fieldData[self.field.fieldId] then diff --git a/gui/CourseGeneratorScreen.lua b/gui/CourseGeneratorScreen.lua index 7532d124f..d7c31c7a4 100644 --- a/gui/CourseGeneratorScreen.lua +++ b/gui/CourseGeneratorScreen.lua @@ -164,7 +164,7 @@ function CourseGeneratorScreen:onClickWidth( state ) end function CourseGeneratorScreen:onOpenAutoWidth(element) - local autoWidth = courseplay:getWorkWidth(self.vehicle) + local autoWidth = self.settings.workWidth:getAutoWorkWidth() if autoWidth > 0 then element:setVisible(true) else diff --git a/hud.lua b/hud.lua index 221eb8f05..f91ceaa6c 100644 --- a/hud.lua +++ b/hud.lua @@ -787,13 +787,10 @@ function courseplay.hud:updatePageContent(vehicle, page) vehicle.cp.hud.content.pages[page][line][1].text = vehicle.cp.settings.useRealisticDriving:getLabel() vehicle.cp.hud.content.pages[page][line][2].text = vehicle.cp.settings.useRealisticDriving:getText() - elseif entry.functionToCall == 'changeTurnDiameter' then - vehicle.cp.hud.content.pages[page][line][1].text = courseplay:loc('COURSEPLAY_TURN_RADIUS'); - if vehicle.cp.turnDiameterAuto ~= nil or vehicle.cp.turnDiameter ~= nil then - vehicle.cp.hud.content.pages[page][line][2].text = ('%s %d%s'):format(vehicle.cp.turnDiameterAutoMode and '(auto)' or '(mnl)', vehicle.cp.turnDiameter, courseplay:loc('COURSEPLAY_UNIT_METER')); - else - vehicle.cp.hud.content.pages[page][line][2].text = '---'; - end; + elseif entry.functionToCall == 'turnDiameter:changeByX' then + local setting = vehicle.cp.settings.turnDiameter + vehicle.cp.hud.content.pages[page][line][1].text = setting:getLabel() + vehicle.cp.hud.content.pages[page][line][2].text = setting:getText() elseif entry.functionToCall == 'changeWorkWidth' then vehicle.cp.hud.content.pages[page][line][1].text = courseplay:loc('COURSEPLAY_WORK_WIDTH'); if vehicle.cp.manualWorkWidth then @@ -2124,7 +2121,7 @@ function courseplay.hud:setFieldWorkAIDriverContent(vehicle) --page 3 settings self:enablePageButton(vehicle, 3) - self:addSettingsRow(vehicle,nil,'changeTurnDiameter', 3, 1, 1 ) + self:addSettingsRow(vehicle,vehicle.cp.settings.turnDiameter,'changeByX', 3, 1, 1 ) self:addSettingsRow(vehicle,nil,'changeWorkWidth', 3, 2, 1, 0.1 ) self:setupCalculateWorkWidthButton(vehicle,3, 2) self:addRowButton(vehicle,vehicle.cp.settings.convoyActive,'toggle', 3, 3, 1 ) @@ -2186,7 +2183,7 @@ function courseplay.hud:setCombineUnloadAIDriverContent(vehicle,assignedCombines self:addRowButton(vehicle,vehicle.cp.settings.autoDriveMode,'changeByX', 1, 3, 1 ) -- page 3 self:enablePageButton(vehicle, 3) - self:addSettingsRow(vehicle,nil,'changeTurnDiameter', 3, 1, 1 ) + self:addSettingsRow(vehicle,vehicle.cp.settings.turnDiameter,'changeByX', 3, 1, 1 ) self:addSettingsRowWithArrows(vehicle,vehicle.cp.settings.driveOnAtFillLevel,'changeByX', 3, 2, 1 ) self:addSettingsRowWithArrows(vehicle,vehicle.cp.settings.followAtFillLevel,'changeByX', 3, 3, 1 ) @@ -2287,7 +2284,7 @@ function courseplay.hud:setBaleCollectorAIDriverContent(vehicle) --page 3 settings self:enablePageButton(vehicle, 3) - self:addSettingsRow(vehicle,nil,'changeTurnDiameter', 3, 1, 1 ) + self:addSettingsRow(vehicle,vehicle.cp.settings.turnDiameter,'changeByX', 3, 1, 1 ) --page 8 fieldwork settings self:enablePageButton(vehicle, 8) diff --git a/settings.lua b/settings.lua index 28b0b9a07..3b65e3dda 100644 --- a/settings.lua +++ b/settings.lua @@ -50,7 +50,7 @@ function courseplay:setAIDriver(vehicle, mode) else -- give it another try as a fallback level courseplay.infoVehicle(vehicle, 'Retrying initialization in mode 5') - self.cp.settings.driverMode:resetToDefault() + self.cp.settings.driverMode:resetToDefault(true) end end @@ -141,7 +141,7 @@ end; --- These three tool offset function should be handled by the setting. function courseplay:changeToolOffsetX(vehicle, changeBy) - vehicle.cp.settings.toolOffsetX:changeBy(changeBy * 0.1) + vehicle.cp.settings.toolOffsetX:changeBy(changeBy * 0.1,true) vehicle.cp.totalOffsetX = vehicle.cp.settings.toolOffsetX:get(); -- show new setting for a few seconds on the screen courseplay:setCustomTimer(vehicle, 'showWorkWidth', 2); @@ -152,7 +152,7 @@ function courseplay:setAutoToolOffsetX(vehicle) end function courseplay:changeToolOffsetZ(vehicle, changeBy, force, noDraw) - vehicle.cp.settings.toolOffsetZ:changeBy(changeBy * 0.1) + vehicle.cp.settings.toolOffsetZ:changeBy(changeBy * 0.1,true) -- show new setting for a few seconds on the screen courseplay:setCustomTimer(vehicle, 'showWorkWidth', 2); end; @@ -164,7 +164,7 @@ function courseplay:calculateWorkWidth(vehicle, noDraw) return end - courseplay:changeWorkWidth(vehicle, nil, courseplay:getWorkWidth(vehicle), noDraw); + courseplay:changeWorkWidth(vehicle, nil,vehicle.cp.courseGeneratorSettings.workWidth:getAutoWorkWidth(), noDraw); end; @@ -221,21 +221,6 @@ function courseplay:changeWorkWidth(vehicle, changeBy, force, noDraw) end; - -function courseplay:changeTurnDiameter(vehicle, changeBy) - vehicle.cp.turnDiameter = vehicle.cp.turnDiameter + changeBy; - vehicle.cp.turnDiameterAutoMode = false; - - if vehicle.cp.turnDiameter < 0.5 then - vehicle.cp.turnDiameter = 0; - end; - - if vehicle.cp.turnDiameter <= 0 then - vehicle.cp.turnDiameterAutoMode = true; - vehicle.cp.turnDiameter = vehicle.cp.turnDiameterAuto - end; -end - --legancy Code in toolManager still using it! function courseplay:changeReverseSpeed(vehicle, changeBy, force, forceReloadPage) local speed = force or (vehicle.cp.speeds.reverse + changeBy); @@ -622,14 +607,6 @@ function courseplay:toggleDebugChannel(self, channel, force) end; end; -function courseplay:setMultiTools(vehicle, set) - if vehicle.cp.courseGeneratorSettings.multiTools:get() % 2 == 0 then - courseplay:changeLaneNumber(vehicle, 1) - else - courseplay:changeLaneNumber(vehicle, 0, true) - end; -end; - function courseplay:validateCanSwitchMode(vehicle) vehicle:setCpVar('canSwitchMode', not vehicle:getIsCourseplayDriving() and not vehicle.cp.isRecording and not vehicle.cp.recordingIsPaused and not vehicle.cp.fieldEdge.customField.isCreated,courseplay.isClient); @@ -933,6 +910,8 @@ function Setting:init(name, label, toolTip, vehicle, value) -- override self.xmlKey = name self.xmlAttribute = '#value' + self.events={} + self.debugMpChannel = courseplay.DBG_MULTIPLAYER end -- Get the current value @@ -962,6 +941,10 @@ function Setting:getName() return self.name end +function Setting:getParentName() + return self.parentName +end + function Setting:getToolTip() return courseplay:loc(self.toolTip) end @@ -969,7 +952,6 @@ end -- function only called from network to set synced setting function Setting:setFromNetwork(value) self:set(value,true) - self:onChange() end function Setting:getDebugString() @@ -979,6 +961,7 @@ end --- Set to a specific value function Setting:set(value) self.value = value + self:onChange() end function Setting:onChange() @@ -1026,7 +1009,96 @@ function Setting:actionEvent(actionName, inputValue, callbackState, isAnalog) ---override end ----@class FloatSetting +--- Registers an event that synchronizes a value. +---@param eventFunc function Callback function run on the receiving end of the event. +---@param getValueFunc function Callback function to get the value, which needs synchronizing. +---@param readFunc function Reads the value data stream on the receiving end with this function. +---@param writeFunc function Writes the value data stream from the sender with this function. +function Setting:registerEvent(eventFunc,getValueFunc,readFunc,writeFunc) + local ix = #self.events+1 + local event = { + eventFunc = eventFunc, + getValueFunc = getValueFunc, + readFunc = readFunc, + writeFunc = writeFunc, + ix = ix + } + table.insert(self.events,event) + return ix +end + +--- Registers an event that synchronizes an Int value. +---@param eventFunc function +---@param getValueFunc function +function Setting:registerIntEvent(eventFunc,getValueFunc) + return self:registerEvent(eventFunc,getValueFunc,streamReadInt32,streamWriteInt32) +end + +--- Registers an event that synchronizes an Float value. +---@param eventFunc function +---@param getValueFunc function +function Setting:registerFloatEvent(eventFunc,getValueFunc) + return self:registerEvent(eventFunc,getValueFunc,streamReadFloat32,streamWriteFloat32) +end + +--- Registers an event that synchronizes an Boolean value. +---@param eventFunc function +---@param getValueFunc function +function Setting:registerBoolEvent(eventFunc,getValueFunc) + return self:registerEvent(eventFunc,getValueFunc,streamReadBool,streamWriteBool) +end +--- Registers an event that requests a function call on the receiving end. +---@param eventFunc function +function Setting:registerFunctionEvent(eventFunc) + return self:registerEvent(eventFunc) +end + +--- Gets an event by it's id. +function Setting:getEvent(ix) + return self.events[ix] +end + +--- Raises an event by it's id to synchronize a value, +--- which is defined by a callback function. +function Setting:raiseEvent(eventIx,value) + local event = self:getEvent(eventIx) + value = event.getValueFunc and event.getValueFunc(self) or value + SettingEvent.sendEvent(self.vehicle,self,event,value) +end + +--- Setting debug. +---@param channel number debug channel +function Setting:debug(channel,...) + courseplay.debugFormat(channel,...) +end + +function Setting:debugMp(...) + self:debug(self.debugMpChannel,...) +end + +function Setting:isMpDebugActive() + return courseplay.debugChannels[courseplay.DBG_MULTIPLAYER] +end + +--- Debug for synchronizing on joining a game. +---@param value any the value that gets synchronized. +---@param valueName string the value name +function Setting:debugWriteStream(value,valueName) + if self:isMpDebugActive() then + self:debugMp("Write, container: %s, setting: %s, %s: %s",self.parentName,self.name,valueName or "value",tostring(value)) + end +end + +--- Debug for synchronizing on joining a game. +---@param value any the value that gets synchronized. +---@param valueName string the value name +function Setting:debugReadStream(value,valueName) + if self:isMpDebugActive() then + self:debugMp("Read, container: %s, setting: %s, %s: %s",self.parentName,self.name,valueName or "value",tostring(value)) + end +end + +---@class FloatSetting :Setting FloatSetting = CpObject(Setting) --- @param name string name of this settings, will be used as an identifier in containers and XML --- @param label string text ID in translations used as a label for this setting on the GUI @@ -1035,6 +1107,7 @@ FloatSetting = CpObject(Setting) --- @param value number default value function FloatSetting:init(name, label, toolTip, vehicle, value) Setting.init(self, name, label, toolTip, vehicle, value) + self.DEFAULT_EVENT = self:registerFloatEvent(self.setFromNetwork,self.get) end function FloatSetting:loadFromXml(xml, parentKey) @@ -1049,11 +1122,14 @@ function FloatSetting:saveToXml(xml, parentKey) end function FloatSetting:onWriteStream(stream) - streamDebugWriteFloat32(stream, self:get()) + local value = self:get() + self:debugWriteStream(value) + streamWriteFloat32(stream, value) end function FloatSetting:onReadStream(stream) - local value = streamDebugReadFloat32(stream) + local value = streamReadFloat32(stream) + self:debugReadStream(value) if value then self:setFromNetwork(value) end @@ -1063,7 +1139,21 @@ function FloatSetting:changeByX(x) self:set(self:get()+x) end ----@class IntSetting +function FloatSetting:set(value,noEventSend) + self.value = value + if noEventSend == nil or noEventSend == false then + if self.syncValue then + self:sendEvent(value) + end + end + self:onChange() +end + +function FloatSetting:sendEvent(value) + self:raiseEvent(self.DEFAULT_EVENT) +end + +---@class IntSetting : Setting IntSetting = CpObject(Setting) --- @param name string name of this settings, will be used as an identifier in containers and XML --- @param label string text ID in translations used as a label for this setting on the GUI @@ -1076,6 +1166,7 @@ function IntSetting:init(name, label, toolTip, vehicle,MIN,MAX,value) Setting.init(self, name, label, toolTip, vehicle,value) self.MAX = MAX self.MIN = MIN + self.DEFAULT_EVENT = self:registerIntEvent(self.setFromNetwork,self.get) end function IntSetting:loadFromXml(xml, parentKey) @@ -1090,11 +1181,14 @@ function IntSetting:saveToXml(xml, parentKey) end function IntSetting:onWriteStream(stream) - streamDebugWriteInt32(stream, self:get()) + local value = self:get() + self:debugWriteStream(value) + streamWriteInt32(stream, value) end function IntSetting:onReadStream(stream) - local value = streamDebugReadInt32(stream) + local value = streamReadInt32(stream) + self:debugReadStream(value) if value then self:setFromNetwork(value) end @@ -1119,10 +1213,10 @@ function IntSetting:set(value,noEventSend) end function IntSetting:sendEvent(value) - SettingsListEvent.sendEvent(self.vehicle,self.parentName, self.name, value) + self:raiseEvent(self.DEFAULT_EVENT) end ----@class SettingList +---@class SettingList : Setting SettingList = CpObject(Setting) --- A setting that can have a predefined set of values @@ -1140,6 +1234,8 @@ function SettingList:init(name, label, toolTip, vehicle, values, texts) self.current = 1 -- index of the previous value/text self.previous = 1 + + self.DEFAULT_EVENT = self:registerIntEvent(self.setFromNetwork,self.getNetworkCurrentValue) end -- Get the current value @@ -1330,15 +1426,16 @@ function SettingList:getDebugString() end function SettingList:onWriteStream(stream) - streamDebugWriteInt32(stream, self:getNetworkCurrentValue()) + local value = self:getNetworkCurrentValue() + self:debugWriteStream(value) + streamWriteInt32(stream, value) end function SettingList:onReadStream(stream) - local value = streamDebugReadInt32(stream) + local value = streamReadInt32(stream) + self:debugReadStream(value) if value ~= nil then self:setFromNetwork(value) - else - print(self:getName()..": Error") end end @@ -1347,11 +1444,7 @@ function SettingList:getNetworkCurrentValue() end function SettingList:sendEvent() - if self.vehicle then - SettingsListEvent.sendEvent(self.vehicle,self.parentName, self.name, self.current) - else - GlobalSettingsEvent.sendEvent(self.parentName, self.name, self.current) - end + self:raiseEvent(self.DEFAULT_EVENT) end function SettingList:actionEvent(actionName, inputValue, callbackState, isAnalog) @@ -1561,24 +1654,31 @@ end function DriverModeSetting:loadFromXml(xml, parentKey) -- remember the value loaded from XML for those settings which aren't up to date when loading, -- for example the field numbers - self.valueFromXml = getXMLInt(xml, self:getKey(parentKey)) + self.valueFromXml = Utils.getNoNil(getXMLInt(xml, self:getKey(parentKey)),self.defaultMode) + self:setFromNetwork(self.valueFromXml) end +--- Only allow courseplay:getIsToolCombiValidForCpMode() after all implements are attached +--- and make sure to update the hud. function DriverModeSetting:postInit() - if self.valueFromXml then - self:set(self.valueFromXml,true) - end + self.valueFromXml = nil + self:validateCurrentValue() + self.vehicle.cp.driver:refreshHUD() end function DriverModeSetting:validateCurrentValue() + --- When the AIDriver gets initialized the first time not all + --- implements are attached, so ignore the valid check. + self.validModes = {} - local wasResetToDefault = false for i=1,self.NUM_MODES do local valid = courseplay:getIsToolCombiValidForCpMode(self.vehicle,i) self.validModes[i] = valid or false - if self:get() == i and not valid then - self:resetToDefault() - wasResetToDefault = true + --- Only reset the driver mode from the server + if g_server and self.valueFromXml == nil then + if self:get() == i and not valid then + self:resetToDefault() + end end end end @@ -1593,8 +1693,8 @@ function DriverModeSetting:setAIDriver() courseplay:setAIDriver(self.vehicle, self:get()) end -function DriverModeSetting:resetToDefault() - self:set(self.defaultMode,true) +function DriverModeSetting:resetToDefault(noEventSend) + self:set(self.defaultMode,noEventSend) end function DriverModeSetting:getDefaultMode() @@ -1919,17 +2019,22 @@ function OffsetSetting:init(name, label, toolTip, vehicle, value) end -- increment/decrement offset -function OffsetSetting:changeBy(changeBy) - self.value = courseplay:round(self.value, 1) + changeBy - if abs(self.value) < 0.1 then - self.value = 0 - end +function OffsetSetting:changeBy(changeBy,noEventSend) + self:set(self.value+changeBy,noEventSend) end --- Currently all hud settings use changeByX() or toggle() should consolidate this. --- Also apply the change rate of 0.1 here, so the courseplay:..() function are not needed anymore. -function OffsetSetting:changeByX(changeBy) - self:changeBy(changeBy*0.1) +function OffsetSetting:changeByX(changeBy,noEventSend) + self:changeBy(changeBy*0.1,noEventSend) +end + +function OffsetSetting:set(value,noEventSend) + value = courseplay:round(value, 1) + if abs(value) < 0.1 then + value = 0 + end + FloatSetting.set(self,value,noEventSend) end function OffsetSetting:getTextX() @@ -1963,12 +2068,17 @@ end ToolOffsetXSetting = CpObject(OffsetSetting) function ToolOffsetXSetting:init(vehicle) OffsetSetting.init(self, 'toolOffsetX', 'COURSEPLAY_TOOL_OFFSET_X', 'COURSEPLAY_TOOL_OFFSET_X', vehicle, 0) + self.SET_TO_CONFIGURED_VALUE_EVENT = self:registerFunctionEvent(self.setToConfiguredValue) end --- Set to the configured value if exists, 0 otherwise function ToolOffsetXSetting:setToConfiguredValue() -- set the auto tool offset if exists or 0 - self:set(g_vehicleConfigurations:getRecursively(self.vehicle, self.name) or 0) + if g_server then + self:set(g_vehicleConfigurations:getRecursively(self.vehicle, self.name) or 0) + else + self:raiseEvent(self.SET_TO_CONFIGURED_VALUE_EVENT) + end end function ToolOffsetXSetting:getText() @@ -2036,6 +2146,98 @@ function CombineOffsetZSetting:getText() return self:getTextZ() end + +---@class TurnDiameterSetting : OffsetSetting +TurnDiameterSetting = CpObject(OffsetSetting) +function TurnDiameterSetting:init(vehicle,driverMode) + OffsetSetting.init(self,"turnDiameter","COURSEPLAY_TURN_RADIUS","COURSEPLAY_TURN_RADIUS",vehicle,0) + self.disabledText = courseplay:loc("COURSEPLAY_AUTOMATIC") + self.autoTurnDiameter = FloatSetting("autoTurnDiameter",nil,nil,vehicle, 0) + self.driverMode = driverMode + self.AUTO_TURN_DIAMETER_EVENT = self:registerFloatEvent(self.setAutoTurnDiameterFromNetwork) +end + +function TurnDiameterSetting:getAutoTurnDiameter() + local turnDiameter = self.vehicle.cp.vehicleTurnRadius * 2 + local toolTurnDiameter = AIDriverUtil.getTurningRadius(self.vehicle) * 2 + + -- Check if we have worktools and if we are in a valid mode + if self.driverMode == courseplay.MODE_COMBI + or self.driverMode == courseplay.MODE_OVERLOADER + or self.driverMode == courseplay.MODE_SEED_FERTILIZE + or self.driverMode == courseplay.MODE_FIELDWORK then + + if toolTurnDiameter > turnDiameter then + turnDiameter = toolTurnDiameter + end + end + + return turnDiameter +end + +function TurnDiameterSetting:validateCurrentValue() + if g_server then + self:updateAutoTurnDiameter() + end +end + +function TurnDiameterSetting:updateAutoTurnDiameter() + local value = self:getAutoTurnDiameter() + self.autoTurnDiameter:set(value,true) + self:raiseEvent(self.AUTO_TURN_DIAMETER_EVENT,value) +end + +function TurnDiameterSetting:onReadStream(stream) + OffsetSetting.onReadStream(self,stream) + self.autoTurnDiameter:onReadStream(stream) +end + +function TurnDiameterSetting:onWriteStream(stream) + OffsetSetting.onWriteStream(self,stream) + self.autoTurnDiameter:onWriteStream(stream) +end + +function TurnDiameterSetting:get() + local value = OffsetSetting.get(self) + if value == 0 then + return self.autoTurnDiameter:get() + end + return value +end + +function TurnDiameterSetting:setAutoTurnDiameterFromNetwork(value) + self.autoTurnDiameter:set(value,true) +end + +function TurnDiameterSetting:getText() + if self.value ~= 0 then + return ('%.1f%s'):format( + self.value, + courseplay:loc('COURSEPLAY_UNIT_METER')) + else + return ('%s(%.1f%s)'):format( + self.disabledText, + self:get(), + courseplay:loc('COURSEPLAY_UNIT_METER')) + end +end + +function TurnDiameterSetting:isAutomaticActive() + return self.value == 0 +end + +function TurnDiameterSetting:set(value,noEventSend) + value = courseplay:round(value, 1) + if value < 0.1 then + value = 0 + end + FloatSetting.set(self,value,noEventSend) +end + +function TurnDiameterSetting:changeByX(changeBy,noEventSend) + self:changeBy(changeBy,noEventSend) +end + --- Setting to select a field ---@class FieldNumberSetting : SettingList FieldNumberSetting = CpObject(SettingList) @@ -2790,32 +2992,44 @@ end function SiloSelectedFillTypeSetting:onWriteStream(stream) local size = self:getSize() or 0 - streamDebugWriteInt32(stream, size) - streamDebugWriteBool(stream,self.runCounterActive) + self:debugWriteStream(size,"size") + streamWriteInt32(stream, size) + self:debugWriteStream(self.runCounterActive,"runCounterActive") + streamWriteBool(stream,self.runCounterActive) if size > 0 then for key,data in ipairs(self:getData()) do - streamDebugWriteInt32(stream, data.fillType) + self:debugWriteStream( data.fillType,"fillType") + streamWriteInt32(stream, data.fillType) if self.runCounterActive then - streamDebugWriteInt32(stream, data.runCounter) + self:debugWriteStream( data.runCounter,"runCounter") + streamWriteInt32(stream, data.runCounter) end - streamDebugWriteInt32(stream, data.maxFillLevel) - streamDebugWriteInt32(stream, data.minFillLevel) + self:debugWriteStream( data.maxFillLevel,"maxFillLevel") + streamWriteInt32(stream, data.maxFillLevel) + self:debugWriteStream( data.minFillLevel,"minFillLevel") + streamWriteInt32(stream, data.minFillLevel) end end end function SiloSelectedFillTypeSetting:onReadStream(stream) - local size = streamDebugReadInt32(stream) - self.runCounterActive = streamDebugReadBool(stream) + local size = streamReadInt32(stream) + self:debugReadStream(size,"size") + self.runCounterActive = streamReadBool(stream) + self:debugReadStream(self.runCounterActive,"runCounterActive") if size and size>0 then for key=1,size do - local selectedFillType = streamDebugReadInt32(stream) + local selectedFillType = streamReadInt32(stream) + self:debugReadStream(selectedFillType,"selectedFillType") local counter if self.runCounterActive then - counter = streamDebugReadInt32(stream) + counter = streamReadInt32(stream) + self:debugReadStream(counter,"counter") end - local maxLevel = streamDebugReadInt32(stream) - local minLevel = streamDebugReadInt32(stream) + local maxLevel = streamReadInt32(stream) + self:debugReadStream(maxLevel,"maxLevel") + local minLevel = streamReadInt32(stream) + self:debugReadStream(minLevel,"minLevel") if selectedFillType then self:addLast(self:fillTypeDataToAdd(selectedFillType,counter,maxLevel,minLevel)) end @@ -3355,6 +3569,9 @@ function WorkingToolPositionsSetting:init(name, label, toolTip, vehicle,totalPos --- Store all instances of this setting in a global table, --- for direct access to update their manual tool positions. table.insert(WorkingToolPositionsSetting.Settings,self) + + self.PLAY_POSITION_EVENT = self:registerIntEvent(self.playPosition) + self.SET_OR_CLEAR_POSITION_EVENT = self:registerIntEvent(self.setFromNetwork) end function WorkingToolPositionsSetting:enrichLabels(labels) @@ -3393,11 +3610,15 @@ function WorkingToolPositionsSetting:setOrClearPostion(x,noEventSend) end end if not noEventSend then - WorkingToolPositionsEvents.sendEvent(self.vehicle,self.name,self.NetworkTypes.SET_OR_CLEAR_POSITION,x) + self:raiseEvent(self.SET_OR_CLEAR_POSITION_EVENT,x) end self.vehicle.cp.driver:refreshHUD() end +function WorkingToolPositionsSetting:setFromNetwork(position) + self:setOrClearPostion(position,true) +end + --- Saves all tool positions recursively. ---@param object table vehicle or implement @@ -3447,7 +3668,7 @@ function WorkingToolPositionsSetting:playPosition(x) self.playTestPostion = x end else - WorkingToolPositionsEvents.sendEvent(self.vehicle,self.name,self.NetworkTypes.PLAY_POSITION,x) + self:raiseEvent(self.PLAY_POSITION_EVENT,x) end end @@ -3598,6 +3819,7 @@ end function WorkingToolPositionsSetting:onWriteStream(streamId) for i=1,self.totalPositions do + self:debugWriteStream(self.hasPosition[i]==true,"hasPos: "..i) streamWriteBool(streamId,self.hasPosition[i]==true) end end @@ -3605,6 +3827,7 @@ end function WorkingToolPositionsSetting:onReadStream(streamId) for i=1,self.totalPositions do self.hasPosition[i] = streamReadBool(streamId) + self:debugReadStream(self.hasPosition[i],"hasPos: "..i) end end @@ -4014,6 +4237,7 @@ function CourseDrawModeSetting:isCourseMapVisible() return self:get() == self.COURSE_2D_DISPLAY_2DONLY end + --[[ ---@class SearchCombineAutomaticallySetting : BooleanSetting SearchCombineAutomaticallySetting = CpObject(BooleanSetting) @@ -4078,7 +4302,7 @@ end function SettingsContainer:onReadStream(stream) for k, setting in pairs(self) do - if self.validateSetting(setting) then + if self.validateSetting(setting) and setting.syncValue then setting:onReadStream(stream) end end @@ -4086,7 +4310,7 @@ end function SettingsContainer:onWriteStream(stream) for k, setting in pairs(self) do - if self.validateSetting(setting) then + if self.validateSetting(setting) and setting.syncValue then setting:onWriteStream(stream) end end @@ -4212,12 +4436,12 @@ function SettingsContainer.createVehicleSpecificSettings(vehicle) container:addSetting(MixerWagonToolPositionsSetting, vehicle) container:addSetting(CourseDrawModeSetting,vehicle) container:addSetting(SugarCaneTrailerToolPositionsSetting, vehicle) + container:addSetting(TurnDiameterSetting,vehicle,container.driverMode) return container end - -- do not remove this comment -- vim: set noexpandtab: diff --git a/toolManager.lua b/toolManager.lua index e5cdf8b7f..b54705c92 100644 --- a/toolManager.lua +++ b/toolManager.lua @@ -41,8 +41,12 @@ function courseplay:updateOnAttachOrDetach(vehicle) vehicle.cp.settings:validateCurrentValues() - -- reset tool offset to the preconfigured value if exists - vehicle.cp.settings.toolOffsetX:setToConfiguredValue() + --- Only call these function, as they depend on the vehicle configurations. + if g_server then + -- reset tool offset to the preconfigured value if exists + vehicle.cp.settings.toolOffsetX:setToConfiguredValue() + vehicle.cp.courseGeneratorSettings.workWidth:updateAutoWorkWidth() + end if vehicle.cp.driver then vehicle.cp.driver:refreshHUD() @@ -244,11 +248,6 @@ function courseplay:updateWorkTools(vehicle, workTool, isImplement) end; end; - -- TURN DIAMETER - if g_server ~= nil then - courseplay:setAutoTurnDiameter(vehicle, hasWorkTool); - end - -- TIP REFERENCE POINTS courseplay:setTipRefOffset(vehicle); @@ -377,34 +376,6 @@ function courseplay:setFoldedStates(object) end; -function courseplay:setAutoTurnDiameter(vehicle, hasWorkTool) - courseplay.debugLine(courseplay.DBG_IMPLEMENTS, 3); - local turnRadius, turnRadiusAuto = 10, 10; - - vehicle.cp.turnDiameterAuto = vehicle.cp.vehicleTurnRadius * 2; - courseplay:debug(('%s: Set turnDiameterAuto to %.2fm (2 x vehicleTurnRadius)'):format(nameNum(vehicle), vehicle.cp.turnDiameterAuto), courseplay.DBG_IMPLEMENTS); - local mode = vehicle.cp.settings.driverMode:get() - -- Check if we have worktools and if we are in a valid mode - if hasWorkTool and (mode == courseplay.MODE_COMBI or mode == courseplay.MODE_OVERLOADER or mode == courseplay.MODE_SEED_FERTILIZE or mode == courseplay.MODE_FIELDWORK) then - courseplay:debug(('%s: getHighestToolTurnDiameter(%s)'):format(nameNum(vehicle), vehicle.name), courseplay.DBG_IMPLEMENTS); - - local toolTurnDiameter = AIDriverUtil.getTurningRadius(vehicle) * 2 - - -- If the toolTurnDiameter is bigger than the turnDiameterAuto, then set turnDiameterAuto to toolTurnDiameter - if toolTurnDiameter > vehicle.cp.turnDiameterAuto then - courseplay:debug(('%s: toolTurnDiameter(%.2fm) > turnDiameterAuto(%.2fm), turnDiameterAuto set to %.2fm'):format(nameNum(vehicle), toolTurnDiameter, vehicle.cp.turnDiameterAuto, toolTurnDiameter), courseplay.DBG_IMPLEMENTS); - vehicle.cp.turnDiameterAuto = toolTurnDiameter; - end; - end; - - - if vehicle.cp.turnDiameterAutoMode then - vehicle.cp.turnDiameter = vehicle.cp.turnDiameterAuto; - courseplay:debug(('%s: turnDiameterAutoMode is active: turnDiameter set to %.2fm'):format(nameNum(vehicle), vehicle.cp.turnDiameterAuto), courseplay.DBG_IMPLEMENTS); - end; - courseplay.debugLine(courseplay.DBG_IMPLEMENTS, 1); -end; - function courseplay:addCpNilTempFillLevelFunction() local cpNilTempFillLevel = function(self, state) if state ~= self.state and state == BunkerSilo.STATE_CLOSED then diff --git a/turn.lua b/turn.lua index ae4ab7fec..04c463664 100644 --- a/turn.lua +++ b/turn.lua @@ -162,7 +162,7 @@ function courseplay:turn(vehicle, dt, turnContext) --- Get the turn radius either by the automatic or user provided turn circle. local extRadius = 0.5 + (0.15 * directionNodeToTurnNodeLength); -- The extra calculation is for dynamic trailer length to prevent jackknifing; - turnInfo.turnRadius = vehicle.cp.turnDiameter * 0.5 + extRadius; + turnInfo.turnRadius = vehicle.cp.settings.turnDiameter:get() * 0.5 + extRadius; turnInfo.turnDiameter = turnInfo.turnRadius * 2; @@ -1534,7 +1534,7 @@ see https://ggbm.at/RN3cawGc function courseplay:getAlignWpsToTargetWaypoint( vehicle, vx, vz, tx, tz, tDirection, generateStraightWaypoints ) vehicle.cp.turnTargets = {} -- make the radius a bit bigger to make sure we can make the turn - local turnRadius = 1.1 * vehicle.cp.turnDiameter / 2 + local turnRadius = 1.1 * vehicle.cp.settings.turnDiameter:get() / 2 -- target waypoint we want to reach local wpNode = courseplay.createNode( "wpNode", tx, tz, tDirection ) -- which side of the target node are we? @@ -2113,7 +2113,7 @@ end ---@return Course function TurnContext:createEndingTurnCourse(vehicle, corner) local startAngle = math.deg(self:getNodeDirection(AIDriverUtil.getDirectionNode(vehicle))) - local r = vehicle.cp.turnDiameter / 2 + local r = vehicle.cp.settings.turnDiameter:get() / 2 local startPos, endPos = {}, {} startPos.x, _, startPos.z = getWorldTranslation(AIDriverUtil.getDirectionNode(vehicle)) endPos.x, _, endPos.z = getWorldTranslation(self.vehicleAtTurnEndNode)