-- ============================================================================
-- === AdblueConsumer.Lua
-- === Mod by [LSMT] Modding Team 
-- === LS25 /FS25
-- === Script by [LSMT] BaTt3RiE @ 2025
-- === Ver 1.0.5.2
-- === Fügt Fahrzeugen die Fähigkeit hinzu, AdBlue zu verbrauchen und den Motor bei leerem Tank zu drosseln.
-- === Main Code für den Adblue-Verbrauch und die Leistungsbegrenzung.
-- ============================================================================

AdblueConsumer = {}

local ModDir = g_currentModDirectory

source(ModDir .. "script/AdBlueRemainingHoursEvent.lua")

local DEBUG = false -- Setze auf true, um Debug-Logs zu aktivieren

local function debugPrint(...)
    if DEBUG then
        print(...)
    end
end

-- Hilfsfunktion: Formatiert Stunden in "H:MM" Format
local function formatRemainingTime(hours)
    if not hours or hours <= 0 or hours == math.huge then
        return "-- H"
    end
    
    local h = math.floor(hours)
    local m = math.floor((hours - h) * 60)
    
    return string.format("%d:%02d H", h, m)
end

-- Benötigte Spezialisierungen
function AdblueConsumer.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Motorized, specializations)
       and SpecializationUtil.hasSpecialization(FillUnit, specializations)
end

-- Wird beim Laden des Spiels aufgerufen
function AdblueConsumer.initSpecialization()
    local schemaS = Vehicle.xmlSchemaSavegame
    local schema = Vehicle.xmlSchema

    schema:register(XMLValueType.INT,   "vehicle.motorized.consumerConfigurations.consumerConfiguration.consumer(?)#fillUnitIndex", "FillUnit-Index für Consumer")
    schema:register(XMLValueType.FLOAT, "vehicle.motorized.consumerConfigurations.consumerConfiguration.consumer(?)#usage",         "Verbrauch pro Stunde")
    schema:register(XMLValueType.STRING,"vehicle.motorized.consumerConfigurations.consumerConfiguration.consumer(?)#fillType",      "Typ des Verbrauchsstoffs (z.B. def)")
end

function AdblueConsumer.registerFunctions(vehicleType)
    SpecializationUtil.registerFunction(vehicleType, "getAdBlueConsumption", AdblueConsumer.getAdBlueConsumption)
    SpecializationUtil.registerFunction(vehicleType, "getAdBlueLevel",       AdblueConsumer.getAdBlueLevel)
    SpecializationUtil.registerFunction(vehicleType, "loadSavedFillLevel",   AdblueConsumer.loadSavedFillLevel)
    SpecializationUtil.registerFunction(vehicleType, "setupDefFillPoint",    AdblueConsumer.setupDefFillPoint)
    SpecializationUtil.registerFunction(vehicleType, "setAdBlueEmptyLimitations",    AdblueConsumer.setAdBlueEmptyLimitations)
    SpecializationUtil.registerFunction(vehicleType, "toggleHUDPositioningMode", AdblueConsumer.toggleHUDPositioningMode)
end

function AdblueConsumer.registerEventListeners(vehicleType)
    SpecializationUtil.registerEventListener(vehicleType, "onLoad",                  AdblueConsumer)
    SpecializationUtil.registerEventListener(vehicleType, "onPostLoad",              AdblueConsumer)
    SpecializationUtil.registerEventListener(vehicleType, "onLoadFinished",          AdblueConsumer)
    SpecializationUtil.registerEventListener(vehicleType, "onUpdate",                AdblueConsumer)
    SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents",  AdblueConsumer)
    SpecializationUtil.registerEventListener(vehicleType, "onDeactivate",            AdblueConsumer)
end

function AdblueConsumer.registerOverwrittenFunctions(vehicleType)
    SpecializationUtil.registerOverwrittenFunction(vehicleType, "onPlayerEnterVehicle", AdblueConsumer.onPlayerEnterVehicleOverwrite)
end

-- onLoad: Ruft Giants auf, sobald das Fahrzeug begonnen wird zu laden
function AdblueConsumer:onLoad(savegame)
    print("AdBlue Consumer loadet")
    self.spec_adblueConsumer = {}
    local spec = self.spec_adblueConsumer

    spec.actionEvents = {}

    -- Markiere, dass noch geladen wird
    spec.isLoading = true

    spec.enabled       = false
    spec.hasAdBlue     = false
    spec.fillUnitIndex = nil

    -- Neue Variablen für dynamische Leistungsbegrenzung
    spec.isPerformanceLimited = false
    spec.performanceFactor = 1.0  -- Volle Leistung als Standard
    spec.originalTorqueCurve = nil
    spec.originalMaxRpm = nil

    -- Suche in der XML nach einem Consumer-Eintrag "def"
    local hasBuiltInDef = false
    local defConsumer   = nil
    local i = 0

    while true do
        local consumerKey = string.format("vehicle.motorized.consumerConfigurations.consumerConfiguration.consumer(%d)", i)
        if not self.xmlFile:hasProperty(consumerKey) then
            break
        end
        
        local fillType = self.xmlFile:getValue(consumerKey .. "#fillType")
        if fillType == "def" then
            hasBuiltInDef = true
            defConsumer = {
                fillUnitIndex = self.xmlFile:getValue(consumerKey .. "#fillUnitIndex"),
                usage         = self.xmlFile:getValue(consumerKey .. "#usage")
            }
            debugPrint(string.format("Eingebauter DEF-Consumer gefunden: FillUnitIndex=%s, Verbrauch=%s l/h",
                       tostring(defConsumer.fillUnitIndex), tostring(defConsumer.usage)))
            break
        end
        i = i + 1
    end

    if not hasBuiltInDef then
        spec.enabled = false
        debugPrint(string.format("Keine DEF-Definition in vehicle.xml gefunden - Deaktiviert für: %s", tostring(self.typeName)))
        return
    end

    spec.enabled                  = true
    spec.hasBuiltInDEF            = hasBuiltInDef
    spec.builtInDEFConsumerIndex  = nil
    spec.builtInDEFFillUnitIndex  = defConsumer and defConsumer.fillUnitIndex or nil
    spec.adblueConsumptionPerHour = defConsumer and defConsumer.usage or 1.0

    -- Filltype=DEF?
    if FillType.DEF ~= nil then
        spec.adBlueFillType = FillType.DEF
        debugPrint(string.format("Benutze DEF-FillType mit Index %d", FillType.DEF))
    else
        debugPrint("WARNUNG: Kein DEF-Filltype im Spiel registriert!")
        spec.adBlueFillType = nil
    end
end

-- Action Events für HUD-Positionierung registrieren
function AdblueConsumer:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
    if self.isClient then
        local spec = self.spec_adblueConsumer
        
        local _, actionEventId = self:addActionEvent(
            spec.actionEvents,
            "ADBLUE_HUD_TOGGLE_POSITIONING",
            self,
            AdblueConsumer.actionTogglePositioning,
            false,
            true,
            false,
            true,
            nil
        )
        
        if actionEventId then
            g_inputBinding:setActionEventTextVisibility(actionEventId, false)
            g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_LOW)
            debugPrint("[AdblueConsumer] HUD-Positionierung Action Event registriert")
        end
    end
end

-- Action Event Handler für Toggle-Taste
function AdblueConsumer.actionTogglePositioning(self, actionName, inputValue, callbackState, isAnalog)
    if inputValue ~= 1 then return end
    
    self:toggleHUDPositioningMode()
end

-- Toggle-Funktion für den Positionierungsmodus
function AdblueConsumer:toggleHUDPositioningMode()
    local spec = self.spec_adblueConsumer
    
    -- Prüfen ob Fahrzeug AdBlue hat
    if not spec.hasAdBlue then
        print("Dieses Fahrzeug hat kein AdBlue - Positionierungsmodus nicht verfügbar!")
        return
    end
    
    -- Zugriff auf SpeedMeterDisplayExt (globale Variable)
    if SpeedMeterDisplayExt then
        local shouldShowHUD = false
        
        if SpeedMeterDisplayExt.isPositioningMode then
            shouldShowHUD = true
        elseif spec.hasAdBlue then
            local fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
            local capacity = self:getFillUnitCapacity(spec.fillUnitIndex)
            shouldShowHUD = fillLevel ~= nil and capacity ~= nil and capacity > 0
        end
        
        if shouldShowHUD then
            SpeedMeterDisplayExt.isPositioningMode = not SpeedMeterDisplayExt.isPositioningMode
            g_inputBinding:setShowMouseCursor(SpeedMeterDisplayExt.isPositioningMode)
            print(string.format("HUD-Positionierungsmodus: %s", tostring(SpeedMeterDisplayExt.isPositioningMode)))
        else
            print("HUD-Positionierungsmodus kann nur aktiviert werden, wenn die AdBlue-Anzeige sichtbar ist!")
        end
    else
        print("SpeedMeterDisplayExt nicht geladen!")
    end
end

-- Positionierungsmodus beim Fahrzeugwechsel deaktivieren
function AdblueConsumer:onDeactivate()
    if SpeedMeterDisplayExt and SpeedMeterDisplayExt.isPositioningMode then
        SpeedMeterDisplayExt.isPositioningMode = false
        g_inputBinding:setShowMouseCursor(false)
        debugPrint("HUD-Positionierungsmodus beim Fahrzeugwechsel deaktiviert")
    end
end

function AdblueConsumer:onLoadFinished()
    local spec = self.spec_adblueConsumer
    spec.isLoading = false
    debugPrint("AdBlue Consumer: Ladevorgang abgeschlossen")
end

-- onPostLoad: Giants ruft das NACH onLoad auf
function AdblueConsumer:onPostLoad(savegame)
    local spec = self.spec_adblueConsumer
    if not spec.enabled then
        return
    end

    if spec.adBlueFillType == nil then
        debugPrint("AdBlue FillType fehlt - AdBlueConsumer deaktiviert")
        spec.enabled = false
        return
    end

    -- Prüfe Diesel-Nutzung
    local hasDiesel = false
    if self.spec_motorized and self.spec_motorized.consumersByFillType then
        if FillType.DIESEL and self.spec_motorized.consumersByFillType[FillType.DIESEL] then
            hasDiesel = true
        else
            for fillTypeId, consumer in pairs(self.spec_motorized.consumersByFillType) do
                local ftName = g_fillTypeManager:getFillTypeNameByIndex(fillTypeId)
                if ftName and (string.find(string.lower(ftName), "diesel") or string.find(string.lower(ftName), "fuel")) then
                    hasDiesel = true
                    break
                end
            end
        end
    end

    if not hasDiesel then
        debugPrint(string.format("Kein Diesel-Verbrauch, AdBlue deaktiviert: %s", tostring(self.typeName)))
        spec.enabled = false
        return
    end

    -- Falls ein DEF Consumer bereits eingebaut ist, Hole fillUnit-Index usw.
    if self.spec_motorized and self.spec_motorized.consumersByFillType then
        local defFillType = spec.adBlueFillType
        if self.spec_motorized.consumersByFillType[defFillType] then
            local consumer = self.spec_motorized.consumersByFillType[defFillType]
            spec.hasBuiltInDEF          = true
            spec.builtInDEFConsumerIndex= consumer.consumerIndex
            spec.builtInDEFFillUnitIndex= consumer.fillUnitIndex
            if self.spec_motorized.consumers and consumer.consumerIndex then
                local builtInConsumer = self.spec_motorized.consumers[consumer.consumerIndex]
                if builtInConsumer then
                    -- Hole eingestellten Verbrauch
                    spec.adblueConsumptionPerHour = builtInConsumer.usage or spec.adblueConsumptionPerHour
                    debugPrint(string.format("Verbrauch aus builtIn: %.1f l/h", spec.adblueConsumptionPerHour))

                    -- Kapazität aus dem FillUnit
                    if spec.builtInDEFFillUnitIndex and self.spec_fillUnit then
                        local fillUnit = self.spec_fillUnit.fillUnits[spec.builtInDEFFillUnitIndex]
                        if fillUnit then
                            spec.capacity = fillUnit.capacity
                            debugPrint(string.format("AdBlue-Kapazität: %.2f", spec.capacity or 0))
                        end
                    end
                end
            end
            spec.fillUnitIndex = spec.builtInDEFFillUnitIndex
            spec.hasAdBlue     = true

            debugPrint(string.format(
                "DEF bereits eingebaut (ConsumerIndex=%s, FillUnitIndex=%s) -> AdBlue konfiguriert!",
                tostring(spec.builtInDEFConsumerIndex),
                tostring(spec.builtInDEFFillUnitIndex)
            ))

            -- Erzeuge FillPoint
            self:setupDefFillPoint()
            -- Lade initial FillLevel
            self:loadSavedFillLevel(savegame)

            consumer.permanentConsumption = false -- Danke an BigFood2307 für den Fix
        else
            debugPrint("Kein eingebauter DEF-Consumer gefunden -> keine AdBlue-Nutzung")
        end
    end
end

-- Richtet evtl. einen DEF-FillNode ein, falls keiner existiert
function AdblueConsumer:setupDefFillPoint()
    local spec = self.spec_adblueConsumer
    if not spec.hasAdBlue or not spec.fillUnitIndex then
        return
    end

    local fillUnitSpec = self.spec_fillUnit
    if not fillUnitSpec then
        debugPrint("Keine FillUnit-Spezialisierung gefunden - kein exactFillRootNode für DEF.")
        return
    end

    local defFillNode = I3DUtil.getChildByName(self.rootNode, "exactFillRootNodeDEF", false)
    if not defFillNode or defFillNode == 0 then
        -- Suche Diesel-FillNode
        local fuelFillNode = I3DUtil.getChildByName(self.rootNode, "exactFillRootNodeFuel", false)
        if not fuelFillNode or fuelFillNode == 0 then
            fuelFillNode = I3DUtil.getChildByName(self.rootNode, "exactFillRootNode", false)
        end
        if fuelFillNode and fuelFillNode ~= 0 then
            local parent = getParent(fuelFillNode)
            local newDefFillNode = clone(fuelFillNode, false, false, false)
            setName(newDefFillNode, "exactFillRootNodeDEF")
            link(parent, newDefFillNode)
            defFillNode = newDefFillNode
            debugPrint("exactFillRootNodeDEF erstellt (Klon von Diesel-FillNode)")
        else
            debugPrint("Kein Fuel-FillNode vorhanden. Kann keinen DEF-Knoten erstellen!")
            return
        end
    end

    if defFillNode and defFillNode ~= 0 then
        local fillUnit = fillUnitSpec.fillUnits[spec.fillUnitIndex]
        if fillUnit then
            fillUnitSpec.exactFillRootNodeToFillUnit[defFillNode] = fillUnit
            fillUnitSpec.exactFillRootNodeToExtraDistance[defFillNode] = 0
            fillUnitSpec.hasExactFillRootNodes = true
            g_currentMission:addNodeObject(defFillNode, self)
            debugPrint(string.format("DEF-FillNode registriert für FillUnit %d", spec.fillUnitIndex))
        end
    end
end

-- Wird in onPostLoad aufgerufen, um initialen AdBlue-Füllstand einzustellen
function AdblueConsumer:loadSavedFillLevel(savegame)
    local spec = self.spec_adblueConsumer
    if not spec.hasAdBlue or not spec.fillUnitIndex then
        return
    end

    local fillLevel = nil
    if savegame then
        local path = savegame.key .. string.format(".fillUnit.unit(%d)#fillLevel", (spec.fillUnitIndex - 1))
        fillLevel = savegame.xmlFile:getFloat(path)
        if fillLevel then
            debugPrint(string.format("AdBlue-Füllstand aus Savegame: %.2f L (%s)", fillLevel, path))
        end
    end

    if not fillLevel then
        local capacity = self:getFillUnitCapacity(spec.fillUnitIndex) or 100
        fillLevel = capacity * 1.0 -- Standardwert 100% (1.0)
        debugPrint(string.format("Kein AdBlue-Füllstand im Savegame -> Standard: %.2f L", fillLevel))
    end

    local currentLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
    local diff = fillLevel - currentLevel
    if math.abs(diff) > 0.001 then
        -- Nur der Server soll das ändern
        if g_server then
            self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.fillUnitIndex, diff, spec.adBlueFillType, ToolType.UNDEFINED)
        end
        debugPrint(string.format("DEF/AdBlue-Tank gesetzt auf: %.2f L", fillLevel))
        self:raiseDirtyFlags(self.spec_fillUnit.dirtyFlag)
    end

    spec.initialFillDone = true
end

-- Die dynamische Leistungsbegrenzung
function AdblueConsumer:setAdBlueEmptyLimitations(isLimited)
    local spec = self.spec_adblueConsumer
    
    if spec.isPerformanceLimited == isLimited then
        return -- Status hat sich nicht geändert
    end
    
    spec.isPerformanceLimited = isLimited
    
    -- Motorisiertes Fahrzeug? 
    if self.spec_motorized and self.spec_motorized.motor then
        local motor = self.spec_motorized.motor
        
        if isLimited then
            -- Torque-Kurve speichern, falls noch nicht geschehen
            if spec.originalTorqueCurve == nil then
                spec.originalTorqueCurve = {}
                spec.originalMaxRpm = motor.maxRpm
                
                -- Ursprüngliche Werte sichern
                for i, keyframe in ipairs(motor.torqueCurve.keyframes) do
                    spec.originalTorqueCurve[i] = {
                        time = keyframe.time,
                        value = keyframe.value
                    }
                end
            end
            
            -- Motorleistung auf 10% begrenzen (basierend auf aktuellen Werten)
            for i, keyframe in ipairs(motor.torqueCurve.keyframes) do
                -- Sicher auf Original-Torque-Werte zugreifen
                if spec.originalTorqueCurve ~= nil and 
                   spec.originalTorqueCurve[i] ~= nil and
                   spec.originalTorqueCurve[i].value ~= nil then
                    motor.torqueCurve.keyframes[i].value = spec.originalTorqueCurve[i].value * 0.01     --Leistun um 99% reduzieren
                end
            end
            
            -- Motor-Drehzahl begrenzen
            if spec.originalMaxRpm ~= nil then
                motor.maxRpm = math.min(motor.maxRpm, motor.minRpm + (spec.originalMaxRpm - motor.minRpm) * 0.1) --Getriebe Leistung 0.5 Optimal
            end
            
            -- Motorparameter neu berechnen
            if self.updateMotorProperties ~= nil then
                self:updateMotorProperties()
            end
            
        else
            -- Originalwerte wiederherstellen
            if spec.originalMaxRpm ~= nil then
                motor.maxRpm = spec.originalMaxRpm
            end
            
            -- Torque-Kurve wiederherstellen
            if spec.originalTorqueCurve ~= nil then
                for i, keyframe in ipairs(spec.originalTorqueCurve) do
                    if i <= #motor.torqueCurve.keyframes then
                        motor.torqueCurve.keyframes[i].value = keyframe.value
                    end
                end
            end
            
            -- Motorparameter neu berechnen
            if self.updateMotorProperties ~= nil then
                self:updateMotorProperties()
            end
        end
        
        debugPrint(string.format("Motor-Leistungsbegrenzung: %s, Torque-Kurve-Elemente: %d", 
                          isLimited and "Aktiv" or "Inaktiv",
                          spec.originalTorqueCurve and #spec.originalTorqueCurve or 0))

        -- Nach der Änderung der Motorparameter die Dirty-Flags setzen
        self:raiseDirtyFlags(self.spec_motorized.dirtyFlag)
    end
end

-- Die Hauptupdate-Funktion: Verbrauch simulieren

function AdblueConsumer:onUpdate(dt)
    local spec = self.spec_adblueConsumer
    if not spec.enabled or not spec.hasAdBlue or not spec.fillUnitIndex then
        return
    end

    -- Prüfe ob Tank (fast) leer ist und begrenze dann die Leistung
    local fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
    local capacity = self:getFillUnitCapacity(spec.fillUnitIndex)
    local criticalThreshold = 0.01

    -- Leistungslimitierung für alle Clients und Server
    if self:getIsMotorStarted() then
        if fillLevel <= criticalThreshold then
            self:setAdBlueEmptyLimitations(true)
        else
            self:setAdBlueEmptyLimitations(false)
        end
    else
        self:setAdBlueEmptyLimitations(false)
    end

    -- NUR der Server berechnet und ändert FillLevel UND remainingHours
    if g_server then
        if self:getIsMotorStarted() then
            local motorLoad = math.max(0, self:getMotorLoadPercentage())
            
            local state = AdBlueSettings.adblueUsage or 2
            local usageFactor = 1.0
                
            if state == 1 then
                usageFactor = 0.25
            elseif state == 2 then
                usageFactor = 0.5
            elseif state == 3 then
                usageFactor = 1.0
            elseif state == 4 then
                usageFactor = AdBlueSettings.customUsageFactor or 1.0
            end
                
            local consumptionPerHour = spec.adblueConsumptionPerHour or 5.0
            local adblueUsage = consumptionPerHour * (dt / 3600000) * motorLoad * usageFactor

            local beforeLevel = fillLevel
                
            if beforeLevel > criticalThreshold and adblueUsage > 0 then
                self:addFillUnitFillLevel(self:getOwnerFarmId(),
                                          spec.fillUnitIndex,
                                          -adblueUsage,
                                          spec.adBlueFillType,
                                          ToolType.UNDEFINED)
            end

            local afterLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
            if self.spec_fillUnit and self.spec_fillUnit.fillUnits[spec.fillUnitIndex] then
                self.spec_fillUnit.fillUnits[spec.fillUnitIndex].fillLevelToDisplay = afterLevel
            end

            -- NEU: Berechne remainingHours NUR auf Server (alle 1 Sekunde)
            local UPDATE_INTERVAL = 1000
            if (not spec.lastUpdateTime) or (g_currentMission.time > spec.lastUpdateTime + UPDATE_INTERVAL) then
                local effectiveConsumption = consumptionPerHour * motorLoad * usageFactor
                if effectiveConsumption > 0 and afterLevel > criticalThreshold then
                    spec.remainingHours = afterLevel / effectiveConsumption
                else
                    spec.remainingHours = afterLevel <= criticalThreshold and 0 or math.huge
                end
                spec.lastUpdateTime = g_currentMission.time
            end

            self:raiseDirtyFlags(self.spec_fillUnit.dirtyFlag)

            -- NEU: Sync an Clients NUR alle 1 Sekunde
            local SYNC_INTERVAL = 1000
            if (not spec.lastSyncTime) or (g_currentMission.time > spec.lastSyncTime + SYNC_INTERVAL) then
                local valueToSync = spec.remainingHours or 0
                    
                if valueToSync == math.huge then
                    valueToSync = "--:--"  -- ← String für "unendlich"
                end
                    
                g_server:broadcastEvent(AdBlueRemainingHoursEvent.new(self, valueToSync))
                spec.lastSyncTime = g_currentMission.time
                    
                debugPrint(string.format("[Server] Synced remainingHours: %s", tostring(valueToSync)))
            end

            -- Debug NUR alle 1 Sekunde
            if (not spec.lastDebugTime) or (g_currentMission.time > spec.lastDebugTime + 1000) then
                debugPrint(string.format("AdBlue: %.8f L verbraucht | %.4f -> %.4f L | Last: %.1f%%",
                                     adblueUsage, beforeLevel, afterLevel, motorLoad * 100))
                
                if spec.remainingHours and spec.remainingHours ~= math.huge then
                    local hours = math.floor(spec.remainingHours)
                    local minutes = math.floor((spec.remainingHours - hours) * 60)
                    debugPrint(string.format("Remaining: %d:%02d H", hours, minutes))
                end
                    
                spec.lastDebugTime = g_currentMission.time
            end
        else
            -- Motor ist aus
            spec.remainingHours = math.huge
            
            if (not spec.lastSyncTime) or (g_currentMission.time > spec.lastSyncTime + 5000) then
                g_server:broadcastEvent(AdBlueRemainingHoursEvent.new(self, "--:--"))  -- ← String
                spec.lastSyncTime = g_currentMission.time
            end
        end
    end
end

-- Getter-Funktion
function AdblueConsumer:getAdBlueConsumption()
    return self.spec_adblueConsumer.adblueConsumptionPerHour
end

function AdblueConsumer:getAdBlueLevel()
    local spec = self.spec_adblueConsumer
    if spec.hasAdBlue and spec.fillUnitIndex then
        return self:getFillUnitFillLevel(spec.fillUnitIndex)
    end
    return 0
end

function AdblueConsumer:onPlayerEnterVehicleOverwrite(superFunc, isControlling, playerStyle, farmId, userId)
    -- Originalfunktion ausführen
    superFunc(self, isControlling, playerStyle, farmId, userId)
    
    -- Unser Code für DEF-Synchronisierung
    local spec = self.spec_adblueConsumer
    if spec and spec.enabled and spec.hasAdBlue and spec.fillUnitIndex then
        if self.spec_fillUnit and self.spec_fillUnit.fillUnits[spec.fillUnitIndex] then

            if g_server then
                self:raiseDirtyFlags(self.spec_fillUnit.dirtyFlag)
                debugPrint("DEF-Füllstand Sync-Flag gesetzt (Server)")
            end

            local currentLevel = self:getFillUnitFillLevel(spec.fillUnitIndex)
            self.spec_fillUnit.fillUnits[spec.fillUnitIndex].fillLevelToDisplay = currentLevel
            debugPrint(string.format("DEF-Füllstand Display-Update: %.2f L", currentLevel))
        end
    end
end