Skip to content
This repository has been archived by the owner on May 23, 2023. It is now read-only.

Commit

Permalink
GlobalSettings MP bugfix and AutoRepairSetting (#6580)
Browse files Browse the repository at this point in the history
* GlobalSettings MP bugfix and AutoRepairSetting

- added AutoRepairSetting to enable
  automatic repair while driving
- fixes GlobalSettings sync in MP

* typo autodrive fix

Co-authored-by: Peter Vaiko <[email protected]>
  • Loading branch information
schwiti6190 and pvaiko authored Dec 30, 2020
1 parent feeaf35 commit 279d42c
Show file tree
Hide file tree
Showing 27 changed files with 232 additions and 33 deletions.
8 changes: 5 additions & 3 deletions CombineUnloadAIDriver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2093,9 +2093,11 @@ function CombineUnloadAIDriver.disableProximitySensorForNonCourseplayDriver(unlo
local d = calcDistanceFrom(unloader.rootNode, vehicle.rootNode)
if d < CombineUnloadAIDriver.safeManeuveringDistance then
vehicle.cp.driver:ignoreVehicleProximity(unloader, 3000)
if g_updateLoopIndex % 500 == 0 then
courseplay.infoVehicle(vehicle, 'Proximity sensor deactivated for player driven %s', nameNum(unloader))
end
--TODO: figure out a possible debug channel, if needed

--if g_updateLoopIndex % 500 == 0 then
--courseplay.infoVehicle(vehicle, 'Proximity sensor deactivated for player driven %s', nameNum(unloader))
--end
end
end
end
Expand Down
60 changes: 60 additions & 0 deletions Events/GlobalSettingsEvent.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

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)), 5)
self.parentName = parentName
self.name = name
self.value = value;
return self;
end

function GlobalSettingsEvent:writeStream(streamId, connection)
courseplay:debug("SettingsListEvent:writeStream()",5)
courseplay:debug(('parentName:%s, name:%s, value:%s'):format(tostring(self.parentName), tostring(self.name), tostring(self.value)), 5);

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()",5)
courseplay:debug(('parentName:%s, name:%s, value:%s'):format(tostring(self.parentName), tostring(self.name), tostring(self.value)), 5);

self:run(connection)
end

function GlobalSettingsEvent:run(connection)
courseplay:debug("GlobalSettingsEvent:run()",5)
courseplay:debug(('parentName:%s, name:%s, value:%s'):format(tostring(self.parentName), tostring(self.name), tostring(self.value)), 5);
courseplay[self.parentName][self.name]:setFromNetwork(self.value)

if not connection:getIsServer() then
courseplay:debug("broadcast GlobalSettingsEvent",5)
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", 5)
courseplay:debug(('parentName:%s, name:%s, value:%s'):format(tostring(parentName), tostring(name), tostring(value)), 5);
g_client:getServerConnection():sendEvent(GlobalSettingsEvent:new(parentName, name, value))
else
courseplay:debug("broadcast GlobalSettingsEvent", 5)
courseplay:debug(('parentName:%s, name:%s, value:%s'):format(tostring(parentName), tostring(name), tostring(value)), 5);
g_server:broadcastEvent(GlobalSettingsEvent:new(parentName, name, value))
end
end
12 changes: 6 additions & 6 deletions Events/SettingsListEvent.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function SettingsListEvent:emptyNew()
end

function SettingsListEvent:new(vehicle,parentName, name, value)
courseplay:debug(string.format("SettingsListEvent:new(%s, %s, %s, %s)",tostring(vehicle), tostring(name),tostring(parentName), tostring(value)), 5)
courseplay:debug(string.format("SettingsListEvent:new(%s, %s, %s, %s)",nameNum(vehicle), tostring(name),tostring(parentName), tostring(value)), 5)
self.vehicle = nil
self.vehicle = vehicle;
self.parentName = parentName
Expand All @@ -35,14 +35,14 @@ function SettingsListEvent:readStream(streamId, connection) -- wird aufgerufen w
self.value = streamReadInt32(streamId)

courseplay:debug("SettingsListEvent:readStream()",5)
courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(tostring(self.vehicle),tostring(self.parentName), tostring(self.name), tostring(self.value)), 5);
courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(nameNum(self.vehicle),tostring(self.parentName), tostring(self.name), tostring(self.value)), 5);

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()",5)
courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(tostring(self.vehicle),tostring(self.parentName), tostring(self.name), tostring(self.value)), 5);
courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(nameNum(self.vehicle),tostring(self.parentName), tostring(self.name), tostring(self.value)), 5);
if self.vehicle ~= nil then
courseplay:debug("vehicle specific Setting",5)
streamWriteBool(streamId, true)
Expand All @@ -58,7 +58,7 @@ end

function SettingsListEvent:run(connection) -- wir fuehren das empfangene event aus
courseplay:debug("SettingsListEvent:run()",5)
courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(tostring(self.vehicle),tostring(self.parentName), tostring(self.name), tostring(self.value)), 5);
courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(nameNum(self.vehicle),tostring(self.parentName), tostring(self.name), tostring(self.value)), 5);

if self.vehicle then
courseplay:debug("vehicle specific Setting",5)
Expand All @@ -76,11 +76,11 @@ end
function SettingsListEvent.sendEvent(vehicle,parentName, name, value)
if g_server ~= nil then
courseplay:debug("broadcast SettingsListEvent", 5)
courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(tostring(vehicle), tostring(parentName), tostring(name), tostring(value)), 5);
courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(nameNum(vehicle), tostring(parentName), tostring(name), tostring(value)), 5);
g_server:broadcastEvent(SettingsListEvent:new(vehicle,parentName, name, value), nil, nil, vehicle);
else
courseplay:debug("send SettingsListEvent", 5)
courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(tostring(vehicle), tostring(parentName),tostring(name), tostring(value)), 5);
courseplay:debug(('vehicle:%s, parentName:%s, name:%s, value:%s'):format(nameNum(vehicle), tostring(parentName),tostring(name), tostring(value)), 5);
g_client:getServerConnection():sendEvent(SettingsListEvent:new(vehicle,parentName, name, value));
end;
end
Expand Down
2 changes: 2 additions & 0 deletions FieldworkAIDriver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ function FieldworkAIDriver:stopAndRefuel()
self:stopWork()
self:foldImplements()
self.state = self.states.ON_UNLOAD_OR_REFILL_WITH_AUTODRIVE
self.triggerHandler:disableFuelLoading()
self:debug('passing the control to AutoDrive to run the fuel refill course.')
self.vehicle.spec_autodrive:StartDrivingWithPathFinder(self.vehicle, self.vehicle.ad.mapMarkerSelected, -2, self, FieldworkAIDriver.onEndCourse, nil);
end
Expand Down Expand Up @@ -567,6 +568,7 @@ function FieldworkAIDriver:onEndCourse()
if self.state == self.states.ON_UNLOAD_OR_REFILL_COURSE or
self.state == self.states.ON_UNLOAD_OR_REFILL_WITH_AUTODRIVE then
-- unload/refill course ended, return to fieldwork
self.triggerHandler:enableFuelLoading()
self:debug('AI driver in mode %d continue fieldwork at %d/%d waypoints', self:getMode(), self.aiDriverData.continueFieldworkAtWaypoint, self.fieldworkCourse:getNumberOfWaypoints())
self:startFieldworkWithPathfinding(self.aiDriverData.continueFieldworkAtWaypoint)
elseif self.state == self.states.RETURNING_TO_FIRST_POINT then
Expand Down
29 changes: 29 additions & 0 deletions GlobalSettings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,32 @@ function ShowMiniHudSetting:init()
-- set default while we are transitioning from the the old setting to this new one
self:set(false)
end


---@class AutoRepairSetting : SettingList
AutoRepairSetting = CpObject(SettingList)
AutoRepairSetting.OFF = 0
function AutoRepairSetting:init()
SettingList.init(self, 'autoRepair', 'COURSEPLAY_AUTOREPAIR', 'COURSEPLAY_AUTOREPAIR_TOOLTIP', nil,
{AutoRepairSetting.OFF, 25, 70, 99},
{'COURSEPLAY_AUTOREPAIR_OFF', '< 25%', '< 70%', 'COURSEPALY_AUTOREPAIR_ALWAYS'}
)
self:set(0)
end

function AutoRepairSetting:isAutoRepairActive()
return self:get() ~= AutoRepairSetting.OFF
end

function AutoRepairSetting:onUpdateTick(dt, isActive, isActiveForInput, isSelected)
local rootVehicle = self:getRootVehicle()
if courseplay:isAIDriverActive(rootVehicle) then
if courseplay.globalSettings.autoRepair:isAutoRepairActive() then
local repairStatus = (1 - self:getWearTotalAmount())*100
if repairStatus < courseplay.globalSettings.autoRepair:get() then
self:repairVehicle()
end
end
end
end
Wearable.onUpdateTick = Utils.appendedFunction(Wearable.onUpdateTick, AutoRepairSetting.onUpdateTick)
2 changes: 1 addition & 1 deletion base.lua
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ function courseplay:onLoad(savegame)
self.cp.generationPosition = {}
self.cp.generationPosition.hasSavedPosition = false


-- Visual i3D waypoint signs
self.cp.signs = {
crossing = {};
Expand Down Expand Up @@ -405,6 +404,7 @@ function courseplay:onLoad(savegame)
courseplay:validateCanSwitchMode(self);

-- TODO: all vehicle specific settings (HUD or advanced settings dialog) should be moved here
-- TODO: make sure every non global setting, has the vehicle table (self) for multiplayer sync
---@type SettingsContainer
self.cp.settings = SettingsContainer("settings")
self.cp.settings:addSetting(SearchCombineOnFieldSetting, self)
Expand Down
4 changes: 3 additions & 1 deletion course-generator/HybridAStar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,9 @@ function HybridAStar:findPath(start, goal, turnRadius, allowReverse, constraints
analyticPath[1]:setTrailerHeading(pred:getTrailerHeading())
State3D.calculateTrailerHeadings(analyticPath, hitchLength)
if self:isPathValid(analyticPath) then
State3D.printPath(analyticPath, 'ANALYTIC')
--TODO: figure out a possible debug channel, if needed

--State3D.printPath(analyticPath, 'ANALYTIC')
self:debug('Found collision free analytic path (%s) at iteration %d', pathType, self.iterations)
-- remove first node of returned analytic path as it is the same as pred
table.remove(analyticPath, 1)
Expand Down
3 changes: 2 additions & 1 deletion courseplay.lua
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ local function initialize()
'Events/SiloSelectedFillTypeEvent',
'Events/StartStopWorkEvent',
'Events/SettingsListEvent',
'Events/GlobalSettingsEvent',
'Events/AssignedCombinesEvents',
'Events/CourseEvent',
'Events/InfoTextEvent',
Expand Down Expand Up @@ -319,7 +320,7 @@ local function setGlobalData()
courseplay.globalSettings:addSetting(ClickToSwitchSetting)
courseplay.globalSettings:addSetting(ShowMiniHudSetting)
courseplay.globalSettings:addSetting(EnableOpenHudWithMouseGlobalSetting)

courseplay.globalSettings:addSetting(AutoRepairSetting)
courseplay.globalCourseGeneratorSettings = SettingsContainer.createGlobalCourseGeneratorSettings()
courseplay.globalPathfinderSettings = SettingsContainer.createGlobalPathfinderSettings()

Expand Down
9 changes: 5 additions & 4 deletions gui/GlobalSettingsPage.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,20 @@
<GuiElement type="text" profile="multiTextOptionSettingsTitle" />
<GuiElement type="bitmap" profile="multiTextOptionSettingsBg" />
</GuiElement>
</GuiElement>
<!--Layout right-->
<!--

<GuiElement type="boxLayout" profile="ingameMenuSettingsLayout" position="750px -100px" >
-->
<!--Settings-->
<!--
<GuiElement type="multiTextOption" profile="multiTextOptionSettings" onCreate="onCreateGlobalSettingsPage" name="" toolTipElementId="ingameMenuHelpBoxText">

<GuiElement type="multiTextOption" profile="multiTextOptionSettings" onCreate="onCreateGlobalSettingsPage" name="autoRepair" toolTipElementId="ingameMenuHelpBoxText">
<GuiElement type="button" profile="multiTextOptionSettingsLeft" />
<GuiElement type="button" profile="multiTextOptionSettingsRight" />
<GuiElement type="text" profile="multiTextOptionSettingsText" />
<GuiElement type="text" profile="multiTextOptionSettingsTitle" />
<GuiElement type="bitmap" profile="multiTextOptionSettingsBg" />
</GuiElement>
<!--
<GuiElement type="multiTextOption" profile="multiTextOptionSettings" onCreate="onCreateGlobalSettingsPage" name="" toolTipElementId="ingameMenuHelpBoxText">
<GuiElement type="button" profile="multiTextOptionSettingsLeft" />
<GuiElement type="button" profile="multiTextOptionSettingsRight" />
Expand Down
2 changes: 1 addition & 1 deletion modDesc.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<modDesc descVersion="47">
<version>6.03.00017</version>
<version>6.03.00018</version>
<author><![CDATA[Courseplay.devTeam]]></author>
<title><!-- en=English de=German fr=French es=Spanish ru=Russian pl=Polish it=Italian br=Brazilian-Portuguese cs=Chinese(Simplified) ct=Chinese(Traditional) cz=Czech nl=Netherlands hu=Hungary jp=Japanese kr=Korean pt=Portuguese ro=Romanian tr=Turkish -->
<en>CoursePlay SIX</en>
Expand Down
39 changes: 26 additions & 13 deletions settings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1410,13 +1410,17 @@ function IntSetting:set(value,noEventSend)
self.value = value
if noEventSend == nil or noEventSend == false then
if self.syncValue then
SettingsListEvent.sendEvent(self.vehicle,self.parentName, self.name, value)
self:sendEvent(value)
end
end
self:onChange()
end
end

function IntSetting:sendEvent(value)
SettingsListEvent.sendEvent(self.vehicle,self.parentName, self.name, value)
end

---@class SettingList
SettingList = CpObject(Setting)

Expand Down Expand Up @@ -1502,7 +1506,7 @@ function SettingList:setToIx(ix,noEventSend)
self.lastChangeTimeMilliseconds = g_time
if noEventSend == nil or noEventSend == false then
if self.syncValue then
SettingsListEvent.sendEvent(self.vehicle,self.parentName, self.name, self.current)
self:sendEvent()
end
end
end
Expand Down Expand Up @@ -1634,6 +1638,15 @@ end
function SettingList:getNetworkCurrentValue()
return self.current
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
end

---WIP
---Generic LinkedList setting and Interface for LinkedList.lua
---@class LinkedList : Setting
Expand Down Expand Up @@ -1941,8 +1954,8 @@ end
---@class CenterModeSetting : SettingList
CenterModeSetting = CpObject(SettingList)

function CenterModeSetting:init()
SettingList.init(self, 'centerMode', 'COURSEPLAY_CENTER_MODE', '', nil,
function CenterModeSetting:init(vehicle)
SettingList.init(self, 'centerMode', 'COURSEPLAY_CENTER_MODE', '', vehicle,
{
courseGenerator.CENTER_MODE_UP_DOWN,
courseGenerator.CENTER_MODE_CIRCULAR,
Expand All @@ -1961,9 +1974,9 @@ end
---@class NumberOfRowsPerLand
NumberOfRowsPerLandSetting = CpObject(SettingList)

function NumberOfRowsPerLandSetting:init()
function NumberOfRowsPerLandSetting:init(vehicle)
SettingList.init(self, 'numberOfRowsPerLand', 'COURSEPLAY_NUMBER_OF_ROWS_PER_LAND',
'COURSEPLAY_NUMBER_OF_ROWS_PER_LAND_TOOLTIP', nil,
'COURSEPLAY_NUMBER_OF_ROWS_PER_LAND_TOOLTIP', vehicle,
{4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24},
{4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24})
self:set(6)
Expand Down Expand Up @@ -2087,9 +2100,9 @@ end

---@class FoldImplementAtEndSetting : BooleanSetting
FoldImplementAtEndSetting = CpObject(BooleanSetting)
function FoldImplementAtEndSetting:init()
function FoldImplementAtEndSetting:init(vehicle)
BooleanSetting.init(self, 'foldImplementAtEnd', 'COURSEPLAY_SHOULD_FOLD_IMPLEMENT',
'COURSEPLAY_SHOULD_FOLD_IMPLEMENT_TOOLTIP', nil)
'COURSEPLAY_SHOULD_FOLD_IMPLEMENT_TOOLTIP', vehicle)
self:set(true)
end

Expand Down Expand Up @@ -2316,18 +2329,18 @@ end

---@class EnableVisualWaypointsTemporary : BooleanSetting
EnableVisualWaypointsTemporary = CpObject(BooleanSetting)
function EnableVisualWaypointsTemporary:init()
function EnableVisualWaypointsTemporary:init(vehicle)
BooleanSetting.init(self, 'enableVisualWaypointsTemporary', 'COURSEPLAY_ENABLE_VISUAL_WAYPOINTS_TEMPORARY',
'COURSEPLAY_ENABLE_VISUAL_WAYPOINTS_TEMPORARY_TOOLTIP', nil)
'COURSEPLAY_ENABLE_VISUAL_WAYPOINTS_TEMPORARY_TOOLTIP', vehicle)
-- set default while we are transitioning from the the old setting to this new one
self:set(false)
end

---@class EnableOpenHudWithMouseVehicle : BooleanSetting
EnableOpenHudWithMouseVehicle = CpObject(BooleanSetting)
function EnableOpenHudWithMouseVehicle:init()
function EnableOpenHudWithMouseVehicle:init(vehicle)
BooleanSetting.init(self, 'enableOpenHudWithMouseVehicle', 'COURSEPLAY_ENABLE_OPEN_HUD_WITH_MOUSE_VEHICLE',
'COURSEPLAY_YES_NO_ENABLE_OPEN_HUD_WITH_MOUSE_VEHICLE', nil)
'COURSEPLAY_YES_NO_ENABLE_OPEN_HUD_WITH_MOUSE_VEHICLE', vehicle)
-- set default while we are transitioning from the the old setting to this new one
self:set(true)
end
Expand Down Expand Up @@ -2395,7 +2408,7 @@ end
---@class AutomaticUnloadingOnFieldSetting : BooleanSetting
AutomaticUnloadingOnFieldSetting = CpObject(BooleanSetting)
function AutomaticUnloadingOnFieldSetting:init(vehicle)
BooleanSetting.init(self, 'automaticUnloadingOnField', 'COURSEPLAY_UNLOADING_ON_FIELD', 'COURSEPLAY_UNLOADING_ON_FIELD', {'COURSEPLAY_MANUAL','COURSEPLAY_AUTOMATIC'})
BooleanSetting.init(self, 'automaticUnloadingOnField', 'COURSEPLAY_UNLOADING_ON_FIELD', 'COURSEPLAY_UNLOADING_ON_FIELD',vehicle, {'COURSEPLAY_MANUAL','COURSEPLAY_AUTOMATIC'})
self:set(false)
end

Expand Down
1 change: 1 addition & 0 deletions toolManager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ function courseplay:updateWorkTools(vehicle, workTool, isImplement)
if isAllowedOkay and isDisallowedOkay then
courseplay:setMarkers(vehicle, workTool)
vehicle.cp.hasMachinetoFill = true;
local isSprayer, isSowingMachine = courseplay:isSprayer(workTool), courseplay:isSowingMachine(workTool);
vehicle.cp.noStopOnEdge = isSprayer and not (isSowingMachine or workTool.cp.isTreePlanter);
vehicle.cp.noStopOnTurn = isSprayer and not (isSowingMachine or workTool.cp.isTreePlanter);
end;
Expand Down
6 changes: 6 additions & 0 deletions translations/translation_br.xml
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,12 @@

<text name="COURSEPLAY_WAITING_FOR_UNLOADERS" text="waiting for unloaders" />
<text name="COURSEPLAY_WAITING_FOR_LEVELCOMPACTAIDRIVER" text="waiting for Siloworker" />

<text name="COURSEPLAY_AUTOREPAIR" text="Automatic repair" />
<text name="COURSEPLAY_AUTOREPAIR_TOOLTIP" text="Repairs automatically on the Field." />
<text name="COURSEPLAY_AUTOREPAIR_OFF" text="Don't repair" />
<text name="COURSEPALY_AUTOREPAIR_ALWAYS" text="Keep it healthy" />

<!-- Replace marker, do not remove! -->
</texts>
</l10n>
6 changes: 6 additions & 0 deletions translations/translation_cs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,12 @@

<text name="COURSEPLAY_WAITING_FOR_UNLOADERS" text="waiting for unloaders" />
<text name="COURSEPLAY_WAITING_FOR_LEVELCOMPACTAIDRIVER" text="waiting for Siloworker" />

<text name="COURSEPLAY_AUTOREPAIR" text="Automatic repair" />
<text name="COURSEPLAY_AUTOREPAIR_TOOLTIP" text="Repairs automatically on the Field." />
<text name="COURSEPLAY_AUTOREPAIR_OFF" text="Don't repair" />
<text name="COURSEPALY_AUTOREPAIR_ALWAYS" text="Keep it healthy" />

<!-- Replace marker, do not remove! -->
</texts>
</l10n>
Loading

0 comments on commit 279d42c

Please sign in to comment.