/*
 * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce)
 *
 * Copyright (c) 2015 - 2025 CCBlueX
 *
 * LiquidBounce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * LiquidBounce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LiquidBounce. If not, see <https://www.gnu.org/licenses/>.
 */
package net.ccbluex.liquidbounce.features.module.modules.exploit

import net.ccbluex.liquidbounce.event.events.QueuePacketEvent
import net.ccbluex.liquidbounce.event.events.TickPacketProcessEvent
import net.ccbluex.liquidbounce.event.events.TransferOrigin
import net.ccbluex.liquidbounce.event.handler
import net.ccbluex.liquidbounce.features.module.Category
import net.ccbluex.liquidbounce.features.module.ClientModule
import net.ccbluex.liquidbounce.utils.client.PacketQueueManager
import net.ccbluex.liquidbounce.utils.client.chat
import net.ccbluex.liquidbounce.utils.client.markAsError
import net.minecraft.network.packet.s2c.common.CommonPingS2CPacket
import net.minecraft.network.packet.s2c.common.KeepAliveS2CPacket

/**
 * PingSpoof module
 *
 * Spoofs your ping to a specified value.
 */

object ModulePingSpoof : ClientModule("PingSpoof", Category.EXPLOIT) {

    private val delay by int("Delay", 500, 0..25000, "ms")

    @Suppress("unused")
    private val fakeLagHandler = handler<QueuePacketEvent> { event ->
        if (player.isDead || event.origin != TransferOrigin.INCOMING) {
            return@handler
        }

        val packet = event.packet

        event.action = if (packet is KeepAliveS2CPacket || packet is CommonPingS2CPacket) {
            PacketQueueManager.Action.QUEUE
        } else {
            PacketQueueManager.Action.PASS
        }
    }

    @Suppress("unused")
    private val tickHandler = handler<TickPacketProcessEvent> {
        if (mc.isIntegratedServerRunning) {
            chat(markAsError(message("cantEnableInSingleplayer")))
            enabled = false
            return@handler
        }

        // Flush when the delay is reached
        // This will also flush packets that are not KeepAliveS2CPacket or CommonPingS2CPacket,
        // in order to keep packet order intact. However, since we only flush on the received side,
        // this should not be a problem.
        val currentTime = System.currentTimeMillis()
        PacketQueueManager.flush { snapshot ->
            snapshot.origin == TransferOrigin.INCOMING && currentTime - snapshot.timestamp >= delay
        }
    }

}
