-- ============================================================================
-- === HandToolFueling.Lua
-- === Mod by [LSMT] Modding Team 
-- === LS25 /FS25
-- === Script by [LSMT] BaTt3RiE @ 2025
-- === Ver 1.0.0.0
-- ============================================================================

HandToolFueling = {}

local DEBUG = false

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

print("[HandToolFueling] Script loaded")

function HandToolFueling.initSpecialization()
    local schema = HandTool.xmlSchema
    schema:setXMLSpecializationType("HandToolFueling")
    schema:register(XMLValueType.FLOAT, "handTool.fueling#fillRate", "Liters per second", 5.0)
    schema:register(XMLValueType.STRING, "handTool.fueling#fillType", "Fill type (DIESEL or DEF)", "DIESEL")
    schema:register(XMLValueType.NODE_INDEX, "handTool.fueling.vehicleTrigger#node", "Trigger node for vehicle detection")
    schema:register(XMLValueType.NODE_INDEX, "handTool.fueling#soundNode", "Node for 3D sound position")
    SoundManager.registerSampleXMLPaths(schema, "handTool.fueling.sounds", "fueling")
    schema:register(XMLValueType.NODE_INDEX, "handTool.fueling#particleNode", "Particle spawn position")
    schema:register(XMLValueType.STRING, "handTool.fueling#particleFile", "Particle I3D file path")
    schema:register(XMLValueType.NODE_INDEX, "handTool.fueling#rotationNode", "Node to rotate during fueling")
    schema:register(XMLValueType.ANGLE, "handTool.fueling#targetRotation", "Target Y rotation when fueling", 0)
    schema:register(XMLValueType.FLOAT, "handTool.fueling#rotationSpeed", "Rotation speed (rad/s)", 2.0)
    schema:setXMLSpecializationType()
end

function HandToolFueling.prerequisitesPresent(specializations)
    return true
end

function HandToolFueling.registerFunctions(handToolType)
    SpecializationUtil.registerFunction(handToolType, "startFueling", HandToolFueling.startFueling)
    SpecializationUtil.registerFunction(handToolType, "stopFueling", HandToolFueling.stopFueling)
    SpecializationUtil.registerFunction(handToolType, "performFueling", HandToolFueling.performFueling)
    SpecializationUtil.registerFunction(handToolType, "vehicleTriggerCallback", HandToolFueling.vehicleTriggerCallback)
    SpecializationUtil.registerFunction(handToolType, "loadParticleSystem", HandToolFueling.loadParticleSystem)
    SpecializationUtil.registerFunction(handToolType, "startParticles", HandToolFueling.startParticles)
    SpecializationUtil.registerFunction(handToolType, "stopParticles", HandToolFueling.stopParticles)
    SpecializationUtil.registerFunction(handToolType, "updateRotation", HandToolFueling.updateRotation)
end

function HandToolFueling.registerEventListeners(handToolType)
    SpecializationUtil.registerEventListener(handToolType, "onLoad", HandToolFueling)
    SpecializationUtil.registerEventListener(handToolType, "onDelete", HandToolFueling)
    SpecializationUtil.registerEventListener(handToolType, "onUpdate", HandToolFueling)
    SpecializationUtil.registerEventListener(handToolType, "onRegisterActionEvents", HandToolFueling)
    SpecializationUtil.registerEventListener(handToolType, "onHeldEnd", HandToolFueling)
end

function HandToolFueling:onLoad(xmlFile, baseDirectory)
    if self.spec_fueling == nil then
        self.spec_fueling = {}
    end
    
    local spec = self.spec_fueling
    spec.isContinuousFueling = false
    spec.fillRate = xmlFile:getValue("handTool.fueling#fillRate", 5.0)
    
    local fillTypeName = xmlFile:getValue("handTool.fueling#fillType", "DIESEL")
    spec.fillType = g_fillTypeManager:getFillTypeIndexByName(fillTypeName)
    
    if spec.fillType == nil then
        Logging.xmlWarning(xmlFile, "Invalid fillType '%s' - using DIESEL", fillTypeName)
        spec.fillType = FillType.DIESEL
    end

    spec.vehicleTriggerNode = xmlFile:getValue("handTool.fueling.vehicleTrigger#node", nil, self.components, self.i3dMappings)
    
    if spec.vehicleTriggerNode ~= nil then
        addTrigger(spec.vehicleTriggerNode, "vehicleTriggerCallback", self)
        debugPrint(string.format("[HandToolFueling] Vehicle trigger registered: %s", getName(spec.vehicleTriggerNode)))
    else
        print("[HandToolFueling] WARNING: No vehicle trigger node defined!")
    end
    
    spec.vehiclesInTrigger = {}
    
    spec.soundNode = xmlFile:getValue("handTool.fueling#soundNode", nil, self.components, self.i3dMappings)
    
    if self.isClient then
        spec.fuelingSample = g_soundManager:loadSampleFromXML(
            xmlFile, "handTool.fueling.sounds", "fueling", baseDirectory,
            spec.soundNode, 1, AudioGroup.VEHICLE, self.i3dMappings, self
        )
    end

    spec.particleNode = xmlFile:getValue("handTool.fueling#particleNode", nil, self.components, self.i3dMappings)
    local particleFile = xmlFile:getValue("handTool.fueling#particleFile")
    
    spec.rotationNode = xmlFile:getValue("handTool.fueling#rotationNode", nil, self.components, self.i3dMappings)
    spec.targetRotation = xmlFile:getValue("handTool.fueling#targetRotation", 0)
    spec.rotationSpeed = xmlFile:getValue("handTool.fueling#rotationSpeed", 2.0)
    
    spec.isFueling = false
    spec.targetVehicle = nil
    spec.targetVehicleId = nil
    spec.buyingStation = nil
    spec.activateActionEventId = nil
    spec.particleSystem = nil
    spec.particleRootNode = nil
    
    spec.currentRotation = 0
    spec.originalRotation = 0
    spec.isRotating = false
    
    if spec.rotationNode ~= nil then
        local rx, ry, rz = getRotation(spec.rotationNode)
        spec.originalRotation = ry
        spec.currentRotation = ry
        debugPrint(string.format("[HandToolFueling] Rotation node found - Original Y: %.2f°", math.deg(ry)))
    end
    
    if spec.particleNode ~= nil and particleFile ~= nil then
        self:loadParticleSystem(particleFile, baseDirectory)
    end
    
    debugPrint(string.format("[HandToolFueling] Loaded - FillRate: %.1fL/s, FillType: %s", 
        spec.fillRate, g_fillTypeManager:getFillTypeNameByIndex(spec.fillType)))
end

function HandToolFueling:vehicleTriggerCallback(triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
    local spec = self.spec_fueling
    
    if spec == nil then
        return
    end
    
    local vehicle = g_currentMission:getNodeObject(otherActorId)
    
    if vehicle ~= nil and vehicle.spec_fillUnit ~= nil then
        local hasFillType = false
        for i = 1, #vehicle.spec_fillUnit.fillUnits do
            local fillUnit = vehicle.spec_fillUnit.fillUnits[i]
            if fillUnit.supportedFillTypes[spec.fillType] then
                hasFillType = true
                break
            end
        end
        
        if hasFillType then
            if onEnter then
                table.insert(spec.vehiclesInTrigger, vehicle)
                debugPrint(string.format("[HandToolFueling] Vehicle entered trigger: %s", vehicle:getFullName()))
            elseif onLeave then
                for i = #spec.vehiclesInTrigger, 1, -1 do
                    if spec.vehiclesInTrigger[i] == vehicle then
                        table.remove(spec.vehiclesInTrigger, i)
                        debugPrint(string.format("[HandToolFueling] Vehicle left trigger: %s", vehicle:getFullName()))
                        
                        if spec.targetVehicle == vehicle then
                            self:stopFueling()
                            spec.isContinuousFueling = false
                        end
                        break
                    end
                end
            end
        end
    end
end

function HandToolFueling:loadParticleSystem(particleFile, baseDirectory)
    local spec = self.spec_fueling
    local fullPath = Utils.getFilename(particleFile, baseDirectory)
    debugPrint(string.format("[HandToolFueling] Loading particle system: %s", fullPath))
    local rootNode = loadI3DFile(fullPath, false, false, false)
    
    if rootNode ~= nil and rootNode ~= 0 then
        debugPrint(string.format("[HandToolFueling] Particle I3D loaded: %s (ID: %d)", getName(rootNode), rootNode))
        
        local particleSystemNode = nil
        local numChildren = getNumOfChildren(rootNode)
        
        if numChildren > 0 then
            particleSystemNode = getChildAt(rootNode, 0)
        else
            particleSystemNode = rootNode
        end
        
        if spec.particleNode ~= nil then
            link(spec.particleNode, particleSystemNode)
            setTranslation(particleSystemNode, 0, 0, 0)
            setRotation(particleSystemNode, 0, 0, 0)
        end
        
        setVisibility(particleSystemNode, false)
        if getHasClassId(particleSystemNode, ClassIds.PARTICLE_SYSTEM) then
            setEmitCountScale(particleSystemNode, 0)
        end
        
        spec.particleRootNode = rootNode
        spec.particleSystem = particleSystemNode
        
        debugPrint("[HandToolFueling] Particle system loaded and linked")
    else
        print(string.format("[HandToolFueling] ERROR: Failed to load particle I3D: %s", fullPath))
    end
end

function HandToolFueling:startParticles()
    local spec = self.spec_fueling
    
    if spec.particleSystem ~= nil then
        setVisibility(spec.particleSystem, true)
        
        if getHasClassId(spec.particleSystem, ClassIds.PARTICLE_SYSTEM) then
            setEmitCountScale(spec.particleSystem, 1.0)
            debugPrint("[HandToolFueling] Particle system started")
        end
    end
end

function HandToolFueling:stopParticles()
    local spec = self.spec_fueling
    
    if spec.particleSystem ~= nil then
        if getHasClassId(spec.particleSystem, ClassIds.PARTICLE_SYSTEM) then
            setEmitCountScale(spec.particleSystem, 0)
        end
        
        setVisibility(spec.particleSystem, false)
        debugPrint("[HandToolFueling] Particle system stopped")
    end
end

function HandToolFueling:updateRotation(dt)
    local spec = self.spec_fueling
    
    if spec.rotationNode == nil then
        return
    end
    
    local targetRot = spec.isRotating and spec.targetRotation or spec.originalRotation
    local alpha = 1 - math.exp(-spec.rotationSpeed * (dt / 1000))
    spec.currentRotation = spec.currentRotation + (targetRot - spec.currentRotation) * alpha
    local _, ry, rz = getRotation(spec.rotationNode)
    setRotation(spec.rotationNode, spec.currentRotation, ry, rz)
end

function HandToolFueling:onDelete()
    local spec = self.spec_fueling
    
    if spec.vehicleTriggerNode ~= nil then
        removeTrigger(spec.vehicleTriggerNode)
    end
    
    if self.isClient and spec.fuelingSample ~= nil then
        g_soundManager:deleteSample(spec.fuelingSample)
        spec.fuelingSample = nil
    end

    if spec ~= nil and spec.particleRootNode ~= nil then
        delete(spec.particleRootNode)
        spec.particleRootNode = nil
        spec.particleSystem = nil
        debugPrint("[HandToolFueling] Particle system deleted")
    end
end

function HandToolFueling:onUpdate(dt)
    if self.spec_fueling == nil then return end
    local spec = self.spec_fueling

    self:updateRotation(dt)

    if not self:getIsHeld() and not spec.isContinuousFueling then
        return
    end

    spec.targetVehicle = nil
    
    if #spec.vehiclesInTrigger > 0 then
        spec.targetVehicle = spec.vehiclesInTrigger[1]
    end

    if spec.isFueling and spec.targetVehicle ~= nil then
        local vehicle = spec.targetVehicle
        local litersToAdd = spec.fillRate * (dt / 1000)
        
        if vehicle.spec_fillUnit then
            local fillUnitIndex = nil
            for i = 1, #vehicle.spec_fillUnit.fillUnits do
                local fillUnit = vehicle.spec_fillUnit.fillUnits[i]
                if fillUnit.supportedFillTypes[spec.fillType] then
                    fillUnitIndex = i
                    break
                end
            end

            if fillUnitIndex == nil then
                local fillTypeName = g_fillTypeManager:getFillTypeNameByIndex(spec.fillType)
                g_currentMission:showBlinkingWarning(
                    string.format(g_i18n:getText("warning_noMatchingTank"), fillTypeName),
                    2000
                )
                debugPrint(string.format("[HandToolFueling] Vehicle has no %s tank!", fillTypeName))
                self:stopFueling()
                spec.isContinuousFueling = false
                return
            end

            local fillLevel = vehicle:getFillUnitFillLevel(fillUnitIndex)
            local capacity = vehicle:getFillUnitCapacity(fillUnitIndex)

            if fillLevel < capacity then
                local actualFilled = math.min(litersToAdd, capacity - fillLevel)
                
                if g_client ~= nil then
                    g_client:getServerConnection():sendEvent(
                        HandToolFuelingEvent.new(self, vehicle, actualFilled, spec.fillType)
                    )
                else
                    self:performFueling(vehicle, actualFilled, spec.fillType, dt)
                end
            else
                local fillTypeName = g_fillTypeManager:getFillTypeNameByIndex(spec.fillType)
                g_currentMission:showBlinkingWarning(
                    string.format(g_i18n:getText("warning_tankFull"), fillTypeName),
                    2000
                )
                debugPrint("[HandToolFueling] Tank full!")
                HandToolFuelingSoundEvent.sendEvent(self, false)
                
                self:stopFueling()
                spec.isContinuousFueling = false
            end
        end
    end
    
    if spec.activateActionEventId ~= nil then
        if spec.targetVehicle == nil then
            g_inputBinding:setActionEventText(spec.activateActionEventId, 
                g_i18n:getText("action_fuelVehicle"))
        else
            local vehicleName = spec.targetVehicle:getFullName()
            g_inputBinding:setActionEventText(spec.activateActionEventId, 
                string.format(g_i18n:getText("action_fuelVehicleTarget"), vehicleName))
        end
    end
end

function HandToolFueling:performFueling(vehicle, litersToAdd, fillType, dt)
    local spec = self.spec_fueling
    
    if g_server == nil then
        print("[HandToolFueling] ERROR: performFueling called on client!")
        return
    end
    
    local fillUnitIndex = nil
    for i = 1, #vehicle.spec_fillUnit.fillUnits do
        local fillUnit = vehicle.spec_fillUnit.fillUnits[i]
        if fillUnit.supportedFillTypes[fillType] then
            fillUnitIndex = i
            break
        end
    end
    
    if fillUnitIndex == nil then
        debugPrint("[HandToolFueling] ERROR: No matching tank found!")
        HandToolFuelingSoundEvent.sendEvent(self, false)
        
        self:stopFueling()
        spec.isContinuousFueling = false
        return
    end
    local pricePerLiter = 0
    local cost = 0
    
    if spec.buyingStation ~= nil then
        pricePerLiter = spec.buyingStation:getEffectiveFillTypePrice(fillType)
        cost = litersToAdd * pricePerLiter
        
        local farmId = vehicle:getOwnerFarmId()
        local currentMoney = g_currentMission:getMoney(farmId)
        
        if currentMoney < cost then
            g_currentMission:showBlinkingWarning(
                g_i18n:getText("shop_messageNotEnoughMoneyToBuy"),
                3000
            )
            debugPrint(string.format("[HandToolFueling] ❌ Nicht genug Geld! Benötigt: %.2f€ | Vorhanden: %.2f€", 
                cost, currentMoney))
            
            HandToolFuelingSoundEvent.sendEvent(self, false)
            
            self:stopFueling()
            spec.isContinuousFueling = false
            return
        end
    end
    vehicle:addFillUnitFillLevel(vehicle:getOwnerFarmId(), fillUnitIndex, litersToAdd, fillType, ToolType.UNDEFINED)
    
    if cost > 0 then
        g_currentMission:addMoney(-cost, vehicle:getOwnerFarmId(), MoneyType.PURCHASE_FUEL, true)
    end
    
    spec.totalLitersFilled = (spec.totalLitersFilled or 0) + litersToAdd
    spec.totalCost = (spec.totalCost or 0) + cost
    
    if spec.buyingStationPlaceable ~= nil and spec.buyingStationPlaceable.updateFuelingDisplay ~= nil then
        local displayIndex = 0
        
        if self.spec_tethered ~= nil and self.spec_tethered.attachedHolder ~= nil then
            local holder = self.spec_tethered.attachedHolder
            displayIndex = holder.displayIndex or 0
            
            debugPrint(string.format("[HandToolFueling] Using displayIndex %d from holder %d", 
                displayIndex, holder.holderIndex or 0))
        else
            print("[HandToolFueling] WARNING: No tethered holder found, using displayIndex 0")
        end
        
        spec.buyingStationPlaceable:updateFuelingDisplay(
            displayIndex,
            litersToAdd,
            pricePerLiter,
            spec.totalLitersFilled,
            spec.totalCost
        )
    end
    
    spec.lastLogTime = (spec.lastLogTime or 0) + (dt or 16)
    if spec.lastLogTime >= 500 then
        local fillLevel = vehicle:getFillUnitFillLevel(fillUnitIndex)
        local capacity = vehicle:getFillUnitCapacity(fillUnitIndex)
        local percentage = math.floor((fillLevel / capacity) * 100)
        debugPrint(string.format("[HandToolFueling] %d%% | %.1fL/%.0fL | %.3f€/L | Gesamt: %.2f€", 
            percentage, spec.totalLitersFilled, capacity, pricePerLiter, spec.totalCost))
        spec.lastLogTime = 0
    end
end

function HandToolFueling:startFueling(vehicle)
    if self.spec_fueling == nil then return end
    
    local spec = self.spec_fueling
    
    if spec.isFueling then
        return
    end
    
    if vehicle == nil then
        if #spec.vehiclesInTrigger > 0 then
            vehicle = spec.vehiclesInTrigger[1]
        end
    end
    
    if vehicle == nil then
        debugPrint("[HandToolFueling] No vehicle in trigger - cannot start fueling!")
        return
    end
    
    spec.isFueling = true
    spec.targetVehicle = vehicle
    
    HandToolFuelingSoundEvent.sendEvent(self, true)

    self:startParticles()
    spec.isRotating = true
    
    if spec.totalLitersFilled == nil then
        spec.totalLitersFilled = 0
    end
    if spec.totalCost == nil then
        spec.totalCost = 0
    end
    if spec.lastLogTime == nil then
        spec.lastLogTime = 0
    end
    
    debugPrint(string.format("[HandToolFueling] Starting fueling: %s", vehicle:getFullName()))
end

function HandToolFueling:stopFueling()
    if self.spec_fueling == nil then return end
    
    local spec = self.spec_fueling
    
    if spec.isFueling then
        debugPrint(string.format("[HandToolFueling] Stopped fueling - Total: %.1fL for %.2f€", 
            spec.totalLitersFilled or 0, spec.totalCost or 0))
        
        spec.isFueling = false
        
        HandToolFuelingSoundEvent.sendEvent(self, false)
        self:stopParticles()
        spec.isRotating = false
    end
end

function HandToolFueling:onRegisterActionEvents()
    if self.spec_fueling == nil then return end
    if not self:getIsActiveForInput(true) then return end

    local spec = self.spec_fueling

    local _, actionEventId = self:addActionEvent(
        InputAction.ACTIVATE_HANDTOOL,
        self,
        HandToolFueling.actionEventFuel,
        true,
        true,
        true,
        true,
        nil
    )
    spec.activateActionEventId = actionEventId
    g_inputBinding:setActionEventText(actionEventId, g_i18n:getText("action_fuelVehicle"))
    g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_VERY_HIGH)

    local _, toggleEventId = self:addActionEvent(
        InputAction.TOGGLE_FUELING,
        self,
        HandToolFueling.actionEventToggleFueling,
        false,
        true,
        false,
        true,
        nil
    )
    spec.toggleFuelingActionEventId = toggleEventId
    g_inputBinding:setActionEventText(toggleEventId, g_i18n:getText("action_toggleContinuousFueling"))
    g_inputBinding:setActionEventTextPriority(toggleEventId, GS_PRIO_HIGH)
end

function HandToolFueling.actionEventToggleFueling(self, actionName, inputValue, inputValuePrevious, callbackState, isAnalog)
    if self.spec_fueling == nil then return end
    local spec = self.spec_fueling

    if inputValue > 0 then
        spec.isContinuousFueling = not spec.isContinuousFueling
        if spec.isContinuousFueling then
            if #spec.vehiclesInTrigger > 0 then
                self:startFueling(spec.vehiclesInTrigger[1])
            else
                spec.isContinuousFueling = false
                g_currentMission:showBlinkingWarning(
                    g_i18n:getText("warning_noVehicleInRange"),
                    2000
                )
            end
        else
            self:stopFueling()
        end
    end
end

function HandToolFueling.actionEventFuel(self, actionName, inputValue, inputValuePrevious, callbackState, isAnalog)
    if self.spec_fueling == nil then return end
    
    local spec = self.spec_fueling
    
    if inputValue > 0 then
        if not spec.isFueling then
            if #spec.vehiclesInTrigger > 0 then
                self:startFueling(spec.vehiclesInTrigger[1])
            else
                g_currentMission:showBlinkingWarning(
                    g_i18n:getText("warning_noVehicleInRange"),
                    2000
                )
                debugPrint("[HandToolFueling] No vehicle in range to fuel!")
            end
        end
    else
        if spec.isFueling then
            self:stopFueling()
        end
    end
end

function HandToolFueling:onHeldEnd()
    if self.spec_fueling == nil then return end
    local spec = self.spec_fueling
    if not spec.isContinuousFueling then
        self:stopFueling()
    end
end

print("[HandToolFueling] All functions registered")

HandToolFuelingEvent = {}
local HandToolFuelingEvent_mt = Class(HandToolFuelingEvent, Event)

InitEventClass(HandToolFuelingEvent, "HandToolFuelingEvent")

function HandToolFuelingEvent.emptyNew()
    local self = Event.new(HandToolFuelingEvent_mt)
    return self
end

function HandToolFuelingEvent.new(handTool, vehicle, litersToAdd, fillType)
    local self = HandToolFuelingEvent.emptyNew()
    self.handTool = handTool
    self.vehicle = vehicle
    self.litersToAdd = litersToAdd
    self.fillType = fillType
    return self
end

function HandToolFuelingEvent:readStream(streamId, connection)
    self.handTool = NetworkUtil.readNodeObject(streamId)
    self.vehicle = NetworkUtil.readNodeObject(streamId)
    self.litersToAdd = streamReadFloat32(streamId)
    self.fillType = streamReadUIntN(streamId, FillTypeManager.SEND_NUM_BITS)
    self:run(connection)
end

function HandToolFuelingEvent:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.handTool)
    NetworkUtil.writeNodeObject(streamId, self.vehicle)
    streamWriteFloat32(streamId, self.litersToAdd)
    streamWriteUIntN(streamId, self.fillType, FillTypeManager.SEND_NUM_BITS)
end

function HandToolFuelingEvent:run(connection)
    if g_server ~= nil and self.handTool ~= nil and self.vehicle ~= nil then
        self.handTool:performFueling(self.vehicle, self.litersToAdd, self.fillType, 16)
    end
end

HandToolFuelingSoundEvent = {}
local HandToolFuelingSoundEvent_mt = Class(HandToolFuelingSoundEvent, Event)

InitEventClass(HandToolFuelingSoundEvent, "HandToolFuelingSoundEvent")

function HandToolFuelingSoundEvent.emptyNew()
    return Event.new(HandToolFuelingSoundEvent_mt)
end

function HandToolFuelingSoundEvent.new(handTool, shouldPlay)
    local self = HandToolFuelingSoundEvent.emptyNew()
    self.handTool = handTool
    self.shouldPlay = shouldPlay
    return self
end

function HandToolFuelingSoundEvent:readStream(streamId, connection)
    self.handTool = NetworkUtil.readNodeObject(streamId)
    self.shouldPlay = streamReadBool(streamId)
    self:run(connection)
end

function HandToolFuelingSoundEvent:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.handTool)
    streamWriteBool(streamId, self.shouldPlay)
end

function HandToolFuelingSoundEvent:run(connection)
    if self.handTool ~= nil and self.handTool.spec_fueling ~= nil then
        local spec = self.handTool.spec_fueling
        
        if self.handTool.isClient then
            if spec.fuelingSample ~= nil then
                if self.shouldPlay then
                    g_soundManager:playSample(spec.fuelingSample)
                    debugPrint("[HandToolFueling] Sound STARTED (synced)")
                else
                    g_soundManager:stopSample(spec.fuelingSample)
                    debugPrint("[HandToolFueling] Sound STOPPED (synced)")
                end
            end
            
            if spec.particleSystem ~= nil then
                if self.shouldPlay then
                    setVisibility(spec.particleSystem, true)
                    if getHasClassId(spec.particleSystem, ClassIds.PARTICLE_SYSTEM) then
                        setEmitCountScale(spec.particleSystem, 1.0)
                        debugPrint("[HandToolFueling] Particles STARTED (synced)")
                    end
                else
                    if getHasClassId(spec.particleSystem, ClassIds.PARTICLE_SYSTEM) then
                        setEmitCountScale(spec.particleSystem, 0)
                    end
                    setVisibility(spec.particleSystem, false)
                    debugPrint("[HandToolFueling] Particles STOPPED (synced)")
                end
            end
            
            if spec.rotationNode ~= nil then
                spec.isRotating = self.shouldPlay
                if self.shouldPlay then
                    debugPrint("[HandToolFueling] Rotation STARTED (synced)")
                else
                    debugPrint("[HandToolFueling] Rotation STOPPED (synced)")
                end
            end
        end
    end

    if connection ~= nil and not connection:getIsServer() then
        g_server:broadcastEvent(self, false, connection, self.handTool)
    end
end

function HandToolFuelingSoundEvent.sendEvent(handTool, shouldPlay)
    local event = HandToolFuelingSoundEvent.new(handTool, shouldPlay)
    
    if g_currentMission:getIsServer() then
        g_server:broadcastEvent(event)
        event:run(nil)
    else
        g_client:getServerConnection():sendEvent(event)
        event:run(nil)
    end
end

print("[HandToolFueling] Network event registered")