// =========================================================
// Airship Training Tasks (KubeJS + FTB Quests customTask)
// 约定：
// - “持续 X 秒”= setCheckTimer(20) 且 maxProgress = X（每秒+1）
// - “连续保持”任务：条件不满足 -> progress 归零
// - “累计”任务：条件不满足 -> 不累加但不归零
// - 数值一律 Number() 强转，避免 Rhino/Java 类型坑
// =========================================================


// =========================================================
// 穿云：高度 ≥ 350 持续 120 秒（连续）
// TASK: 7ACE457381324918
// =========================================================
;(() => {
  const TASK_ID = '7ACE457381324918'
  const DURATION_SECONDS = 120
  const MIN_Y = 350

  FTBQuestsEvents.customTask(TASK_ID, event => {
    event.maxProgress = DURATION_SECONDS
    event.setCheckTimer(20)

    event.setCheck((task, player) => {
      const ship = VS.js().getShipPlayerIsOnStrict(player)
      if (ship == null) { task.progress = 0; return }

      const pos = VS.js().getShipPosition(ship)
      if (pos == null) { task.progress = 0; return }

      const shipY = Number(pos[1])
      if (!isFinite(shipY)) { task.progress = 0; return }

      if (shipY > MIN_Y) task.progress++
      else task.progress = 0
    })
  })
})()


// =========================================================
// 稳定巡航：速度保持在 [MIN_SPEED, MAX_SPEED] 持续 120 秒（连续）
// TASK: 4800C0DB89717B36
// =========================================================
;(() => {
  const TASK_ID = '4800C0DB89717B36'
  const DURATION_SECONDS = 120
  const MIN_SPEED = 8.50
  const MAX_SPEED = 11.00

  FTBQuestsEvents.customTask(TASK_ID, event => {
    event.maxProgress = DURATION_SECONDS
    event.setCheckTimer(20)

    event.setCheck((task, player) => {
      const ship = VS.js().getShipPlayerIsOnStrict(player)
      if (ship == null) { task.progress = 0; return }

      const speed = Number(VS.js().getShipSpeed(ship))
      if (!isFinite(speed)) { task.progress = 0; return }

      if (speed >= MIN_SPEED && speed <= MAX_SPEED) task.progress++
      else task.progress = 0
    })
  })
})()


// =========================================================
// 航向锁定：方向稳定（点积阈值）持续 60 秒（连续）
// - 要求：在船上 + 速度>=MIN_SPEED + 航向抖动不超过 MAX_DEG_DELTA
// - 换船：重置并重新取基准方向
// TASK: 01DE2052B13EFE68
// =========================================================
;(() => {
  const TASK_ID = '01DE2052B13EFE68'
  const DURATION_SECONDS = 60
  const MIN_SPEED = 5.0
  const MAX_DEG_DELTA = 6.0
  const DEBUG = false

  const KEY_BX   = 'vs_dirstable_bx_01DE2052B13EFE68'
  const KEY_BZ   = 'vs_dirstable_bz_01DE2052B13EFE68'
  const KEY_HAS  = 'vs_dirstable_has_01DE2052B13EFE68'     // "1"
  const KEY_SHIP = 'vs_dirstable_shipid_01DE2052B13EFE68'  // ship.id string

  // 避免 Math.PI 在某些环境异常
  const PI = 3.141592653589793
  const DOT_MIN = Math.cos(MAX_DEG_DELTA * PI / 180.0)

  FTBQuestsEvents.customTask(TASK_ID, event => {
    event.maxProgress = DURATION_SECONDS
    event.setCheckTimer(20)

    event.setCheck((task, player) => {

      const ship = VS.js().getShipPlayerIsOnStrict(player)
      if (ship == null) { if (DEBUG) player.tell('reset: ship==null'); resetAll(task, player); return }

      const speed = Number(VS.js().getShipSpeed(ship))
      if (!isFinite(speed) || speed < MIN_SPEED) { if (DEBUG) player.tell('reset: low speed'); resetAll(task, player); return }

      // 换船：重置并重新初始化基准
      const shipId = '' + ship.id
      const storedShipId = player.persistentData.getString(KEY_SHIP) || ''
      if (storedShipId === '' || storedShipId !== shipId) {
        task.progress = 0
        player.persistentData.putString(KEY_SHIP, shipId)
        player.persistentData.remove(KEY_HAS)
      }

      // 取速度向量（XZ）
      const v = VS.js().getShipVelocity(ship)
      if (v == null) { if (DEBUG) player.tell('reset: vel==null'); resetAll(task, player); return }

      const vx = Number(v[0])
      const vz = Number(v[2])
      if (!isFinite(vx) || !isFinite(vz)) { if (DEBUG) player.tell('reset: vx/vz invalid'); resetAll(task, player); return }

      const h2 = vx * vx + vz * vz
      if (!isFinite(h2) || h2 < 1.0e-6) { if (DEBUG) player.tell('reset: h2 small'); resetAll(task, player); return }

      // 当前方向单位向量
      const invLen = 1 / Math.sqrt(h2)
      const dx = vx * invLen
      const dz = vz * invLen

      // 初始化基准
      const hasBase = (player.persistentData.getString(KEY_HAS) || '') === '1'
      if (!hasBase || task.progress <= 0) {
        player.persistentData.putDouble(KEY_BX, dx)
        player.persistentData.putDouble(KEY_BZ, dz)
        player.persistentData.putString(KEY_HAS, '1')
        task.progress = 1
        if (DEBUG) player.tell(`init base dotMin=${DOT_MIN}`)
        return
      }

      const bx = Number(player.persistentData.getDouble(KEY_BX))
      const bz = Number(player.persistentData.getDouble(KEY_BZ))
      if (!isFinite(bx) || !isFinite(bz)) {
        player.persistentData.putDouble(KEY_BX, dx)
        player.persistentData.putDouble(KEY_BZ, dz)
        player.persistentData.putString(KEY_HAS, '1')
        task.progress = 1
        if (DEBUG) player.tell('re-init base (bx/bz invalid)')
        return
      }

      // 点积判稳定
      const dot = bx * dx + bz * dz
      if (!isFinite(dot)) { if (DEBUG) player.tell('reset: dot invalid'); resetAll(task, player); return }

      if (dot >= DOT_MIN) {
        task.progress++
      } else {
        task.progress = 0
        // 以当前为新基准（更符合直觉）
        player.persistentData.putDouble(KEY_BX, dx)
        player.persistentData.putDouble(KEY_BZ, dz)
        player.persistentData.putString(KEY_HAS, '1')
      }
    })

    function resetAll(task, player) {
      task.progress = 0
      player.persistentData.remove(KEY_HAS)
      player.persistentData.remove(KEY_SHIP)
      player.persistentData.remove(KEY_BX)
      player.persistentData.remove(KEY_BZ)
    }
  })
})()


// =========================================================
// 无人值守：自动巡航（累计）
// - 条件：在船上 + 速度>=MIN_SPEED + 玩家未处于 mount（不掌舵）
// - 累计：条件不满足不加进度，但不重置
// TASK: 7C9E7299CC36F250
// =========================================================
;(() => {
  const TASK_ID = '7C9E7299CC36F250'
  const DURATION_SECONDS = 600
  const MIN_SPEED = 6.0
  const DEBUG = false

  FTBQuestsEvents.customTask(TASK_ID, event => {
    event.maxProgress = DURATION_SECONDS
    event.setCheckTimer(20)

    event.setCheck((task, player) => {
      const ship = VS.js().getShipPlayerIsOnStrict(player)
      if (ship == null) { if (DEBUG) player.tell('skip: not on ship'); return }

      const speed = Number(VS.js().getShipSpeed(ship))
      if (!isFinite(speed) || speed < MIN_SPEED) { if (DEBUG) player.tell('skip: speed low'); return }

      const mountedShip = VS.js().getMountedShip(player)
      if (mountedShip != null) { if (DEBUG) player.tell('skip: steering/mounted'); return }

      if (task.progress < DURATION_SECONDS) task.progress++
      if (DEBUG) player.tell(`add: total=${task.progress}s speed=${speed.toFixed(2)}`)
    })
  })
})()


// =========================================================
// 极速巡航：推力极限
// - 速度保持在 [MIN_SPEED, MAX_SPEED] 持续 30 秒（连续）
// TASK: 5F17F11F4691544D
// =========================================================
;(() => {
  const TASK_ID = '5F17F11F4691544D'
  const DURATION_SECONDS = 30
  const MIN_SPEED = 18.50
  const MAX_SPEED = 20.00

  FTBQuestsEvents.customTask(TASK_ID, event => {
    event.maxProgress = DURATION_SECONDS
    event.setCheckTimer(20)

    event.setCheck((task, player) => {
      const ship = VS.js().getShipPlayerIsOnStrict(player)
      if (ship == null) { task.progress = 0; return }

      const speed = Number(VS.js().getShipSpeed(ship))
      if (!isFinite(speed)) { task.progress = 0; return }

      if (speed >= MIN_SPEED && speed <= MAX_SPEED) task.progress++
      else task.progress = 0
    })
  })
})()


// =========================================================
// 跨域航线：群系跃迁（一次飞行中连续经过多个群系）
// 规则：
// - 仅检测“群系变化”（A->B 计 1 次），可重复（A->B->A 也会继续计数）
// - 玩家中途离开飞艇：进度清零 & 状态清空（一次飞行结束）
// - 防抖：新群系需连续检测 CONFIRM_TICKS 次才确认
// TASK: 1472E12847DEBFE2
// =========================================================

;
(() => {
	FTBQuestsEvents.customTask('1472E12847DEBFE2', event => {

		const REQUIRED_CHANGES = 20
		const CHECK_TIMER = 20
		const CONFIRM_TICKS = 3

		const DEBUG = false
		const DEBUG_EVERY_TICKS = 5 // 每 5 次 check 输出一次概要（5秒一次，因为 checkTimer=20）

		const KEY_LAST = 'vs_biomehop_last_1472E12847DEBFE2'
		const KEY_PEND = 'vs_biomehop_pend_1472E12847DEBFE2'
		const KEY_PENDN = 'vs_biomehop_pendn_1472E12847DEBFE2'
		const KEY_DCNT = 'vs_biomehop_dbgcnt_1472E12847DEBFE2'

		event.maxProgress = REQUIRED_CHANGES
		event.setCheckTimer(CHECK_TIMER)

		event.setCheck((task, player) => {

			// ====== debug 节流计数 ======
			let dc = parseInt(player.persistentData.getString(KEY_DCNT) || '0', 10)
			if (!Number.isFinite(dc) || dc < 0) dc = 0
			dc += 1
			player.persistentData.putString(KEY_DCNT, '' + dc)

			// 1) 是否在船上
			let onShip = VS.js().isPlayerOnShipStrict(player)
			if (!onShip) {
				if (DEBUG) player.tell(`[biomehop] reset: not on ship (prog=${task.progress})`)
				resetAll(task, player)
				return
			}

			// 2) 当前群系ID
			let biomeId = getBiomeId(player)
			if (!biomeId) {
				if (DEBUG && (dc % DEBUG_EVERY_TICKS === 0)) {
					player.tell(`[biomehop] biomeId=null (prog=${task.progress})`)
				}
				return
			}

			let last = player.persistentData.getString(KEY_LAST) || ''
			let pend = player.persistentData.getString(KEY_PEND) || ''
			let pendN = parseInt(player.persistentData.getString(KEY_PENDN) || '0', 10)
			if (!Number.isFinite(pendN) || pendN < 0) pendN = 0

			// 周期性概要输出
			if (DEBUG && (dc % DEBUG_EVERY_TICKS === 0)) {
				player.tell(`[biomehop] onShip=true biome=${biomeId} last=${last || '-'} pend=${pend || '-'} pendN=${pendN} prog=${task.progress}/${REQUIRED_CHANGES}`)
			}

			// 3) 首次初始化 last
			if (last === '') {
				player.persistentData.putString(KEY_LAST, biomeId)
				player.persistentData.remove(KEY_PEND)
				player.persistentData.putString(KEY_PENDN, '0')
				if (DEBUG) player.tell(`[biomehop] init last=${biomeId}`)
				return
			}

			// 4) 群系没变：清 pending
			if (biomeId === last) {
				if (pend !== '' || pendN !== 0) {
					player.persistentData.remove(KEY_PEND)
					player.persistentData.putString(KEY_PENDN, '0')
					if (DEBUG) player.tell(`[biomehop] stable back to last=${last}, clear pending`)
				}
				return
			}

			// 5) 群系变了：pending
			if (pend !== biomeId) {
				player.persistentData.putString(KEY_PEND, biomeId)
				player.persistentData.putString(KEY_PENDN, '1')
				if (DEBUG) player.tell(`[biomehop] detected change ${last} -> ${biomeId} (pending 1/${CONFIRM_TICKS})`)
				return
			}

			// pend == biomeId：累计确认
			pendN += 1
			player.persistentData.putString(KEY_PENDN, '' + pendN)
			if (DEBUG) player.tell(`[biomehop] pending confirm ${biomeId} (${pendN}/${CONFIRM_TICKS})`)

			if (pendN >= CONFIRM_TICKS) {
				if (task.progress < REQUIRED_CHANGES) task.progress++
				player.persistentData.putString(KEY_LAST, biomeId)

				player.persistentData.remove(KEY_PEND)
			    player.persistentData.putString(KEY_PENDN, '0')

				if (DEBUG) player.tell(`[biomehop] ✅ confirmed ${last} -> ${biomeId}, progress=${task.progress}/${REQUIRED_CHANGES}`)
			}
		})

		function resetAll(task, player) {
			task.progress = 0
			player.persistentData.remove(KEY_LAST)
			player.persistentData.remove(KEY_PEND)
			player.persistentData.remove(KEY_PENDN)
			player.persistentData.remove(KEY_DCNT)
		}

		// 兼容取 biome id：优先用 registry key，失败再降级 regex
		function getBiomeId(player) {
			try {
				let holder = player.level.getBiome(player.blockPosition())

				// 方案A：Holder#unwrapKey() -> Optional<ResourceKey<Biome>>
				if (holder && typeof holder.unwrapKey === 'function') {
					let opt = holder.unwrapKey()
					if (opt && typeof opt.isPresent === 'function' && opt.isPresent()) {
						let key = opt.get() // ResourceKey<Biome>
						// ResourceKey#location() -> ResourceLocation
						if (key && typeof key.location === 'function') {
							return String(key.location()) // e.g. "minecraft:plains"
						}
						return String(key)
					}
				}

			} catch (e) {
				return null
			}
		}
	})
})()



// =========================================================
// 长距离飞行：累计飞行距离达到 TARGET_DISTANCE 米（累计）
// 规则：
// - 必须始终在飞艇(船体)上：一旦不在船上 -> 进度清零 & 状态清空
// - 换船（shipId 变化）-> 清零（视为重新开始一次飞行）
// - 每秒采样一次，按船的世界坐标位移累加距离（只算水平 XZ 距离）
// =========================================================

;(() => {
  const TASK_ID = '5E8181786DEB62B9'
  const TARGET_DISTANCE = 5000 // 目标：累计 5000m（自行改）
  const CHECK_TIMER_TICKS = 20 // 1s

  // 可选：单次步进上限（防止传送/加载导致的瞬移把距离刷爆）
  // 不需要就设为 null
  const MAX_STEP_METERS = 150.0

  // persistent keys（加上 TASK_ID 后缀避免冲突）
  const KEY_HAS  = `vs_ld_has_${TASK_ID}`        // "1"
  const KEY_SID  = `vs_ld_shipid_${TASK_ID}`     // ship.id string
  const KEY_LX   = `vs_ld_lastx_${TASK_ID}`      // double
  const KEY_LZ   = `vs_ld_lastz_${TASK_ID}`      // double
  const KEY_ACC  = `vs_ld_acc_${TASK_ID}`        // double

  FTBQuestsEvents.customTask(TASK_ID, event => {
    const TARGET_INT = Math.max(1, Math.floor(Number(TARGET_DISTANCE)))

    event.maxProgress = TARGET_INT
    event.setCheckTimer(CHECK_TIMER_TICKS)

    event.setCheck((task, player) => {
      // 1) 必须在船上（严格判定）
      const ship = VS.js().getShipPlayerIsOnStrict(player)
      if (ship == null) { resetAll(task, player); return }

      // 2) 换船 -> 清零
      const shipId = '' + ship.id
      const storedShipId = player.persistentData.getString(KEY_SID) || ''
      if (storedShipId === '' || storedShipId !== shipId) {
        resetAll(task, player)
        player.persistentData.putString(KEY_SID, shipId)
      }

      // 3) 取船世界坐标（x,y,z）
      const pos = VS.js().getShipPosition(ship)
      if (pos == null || pos.length < 3) { resetAll(task, player); return }

      const x = Number(pos[0])
      const z = Number(pos[2])
      if (!isFinite(x) || !isFinite(z)) { resetAll(task, player); return }

      // 4) 首次采样：只记录，不计距离
      const has = (player.persistentData.getString(KEY_HAS) || '') === '1'
      if (!has) {
        player.persistentData.putDouble(KEY_LX, x)
        player.persistentData.putDouble(KEY_LZ, z)
        player.persistentData.putDouble(KEY_ACC, 0.0)
        player.persistentData.putString(KEY_HAS, '1')
        task.progress = 0
        return
      }

      // 5) 计算水平位移（XZ）
      const lastX = Number(player.persistentData.getDouble(KEY_LX))
      const lastZ = Number(player.persistentData.getDouble(KEY_LZ))
      if (!isFinite(lastX) || !isFinite(lastZ)) { resetAll(task, player); return }

      let dx = x - lastX
      let dz = z - lastZ
      let step = Math.sqrt(dx * dx + dz * dz)
      if (!isFinite(step) || step < 0) step = 0

      // 可选：步进限幅
      if (MAX_STEP_METERS != null && isFinite(MAX_STEP_METERS) && step > MAX_STEP_METERS) {
        step = 0
      }

      // 6) 累加距离（累计）
      let acc = Number(player.persistentData.getDouble(KEY_ACC))
      if (!isFinite(acc) || acc < 0) acc = 0
      acc += step

      // 7) 写回采样点与累计值
      player.persistentData.putDouble(KEY_LX, x)
      player.persistentData.putDouble(KEY_LZ, z)
      player.persistentData.putDouble(KEY_ACC, acc)

      // 8) 任务进度：按“米”映射到整数进度
      //    例：acc=12.7m -> progress=12
      let prog = Math.floor(acc)
      if (!isFinite(prog) || prog < 0) prog = 0
      if (prog > TARGET_INT) prog = TARGET_INT
      task.progress = prog
    })

    function resetAll(task, player) {
      task.progress = 0
      player.persistentData.remove(KEY_HAS)
      player.persistentData.remove(KEY_SID)
      player.persistentData.remove(KEY_LX)
      player.persistentData.remove(KEY_LZ)
      player.persistentData.remove(KEY_ACC)
    }
  })
})()



