Иконка ресурса

FREE FixDeepSeaTransfer : 0.2.0 0.2.0

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using HarmonyLib;
using Oxide.Core.Plugins;
using UnityEngine;

namespace Oxide.Plugins
{

[Info("FixDeepSeaTransfer", "miyagawayuu", "0.2.0")]
[Description("Prevents PlayerBoat passengers from being stranded or killed during Deep Sea transfers.")]
public class FixDeepSeaTransfer : RustPlugin
{
    private static FixDeepSeaTransfer _instance;
    private readonly Dictionary<ulong, int> _deepSeaTransferPlayerScopes =
        new Dictionary<ulong, int>();

    private sealed class DeepSeaPassengerTeleportState
    {
        public BasePlayer Player;
        public Vector3 LocalPosition;
        public bool WasMounted;
    }

    private sealed class DeepSeaVehicleTeleportState
    {
        public BaseEntity Vehicle;
        public readonly List<DeepSeaPassengerTeleportState> Passengers =
            new List<DeepSeaPassengerTeleportState>();
    }

    private void Init()
    {
        _instance = this;
    }

    private void Unload()
    {
        _deepSeaTransferPlayerScopes.Clear();
        _instance = null;
    }

    private static DeepSeaVehicleTeleportState CaptureDeepSeaVehiclePassengers(BaseEntity entity)
    {
        if (!(entity is BaseVehicle) || entity.IsDestroyed)
        {
            return null;
        }

        var state = new DeepSeaVehicleTeleportState
        {
            Vehicle = entity,
        };
        var passengers = new List<BasePlayer>();
        BaseVehicle.GetPassengersForVehicle(entity, passengers);
        foreach (var player in passengers)
        {
            if (player == null || !player.IsConnected || player.IsNpc)
            {
                continue;
            }

            state.Passengers.Add(new DeepSeaPassengerTeleportState
            {
                Player = player,
                LocalPosition = entity.transform.InverseTransformPoint(player.transform.position),
                WasMounted = player.isMounted,
            });
        }

        return state.Passengers.Count > 0 ? state : null;
    }

    private void BeginDeepSeaTransfer(DeepSeaVehicleTeleportState state)
    {
        if (state == null)
        {
            return;
        }

        foreach (var passenger in state.Passengers)
        {
            var player = passenger.Player;
            if (!passenger.WasMounted || player == null)
            {
                continue;
            }

            _deepSeaTransferPlayerScopes.TryGetValue(player.userID, out var depth);
            _deepSeaTransferPlayerScopes[player.userID] = depth + 1;
        }
    }

    private void EndDeepSeaTransfer(DeepSeaVehicleTeleportState state)
    {
        if (state == null)
        {
            return;
        }

        foreach (var passenger in state.Passengers)
        {
            var player = passenger.Player;
            if (!passenger.WasMounted
                || player == null
                || !_deepSeaTransferPlayerScopes.TryGetValue(player.userID, out var depth))
            {
                continue;
            }

            if (depth <= 1)
            {
                _deepSeaTransferPlayerScopes.Remove(player.userID);
            }
            else
            {
                _deepSeaTransferPlayerScopes[player.userID] = depth - 1;
            }
        }
    }

    private bool IsPlayerInDeepSeaTransfer(BasePlayer player)
    {
        return player != null
            && _deepSeaTransferPlayerScopes.TryGetValue(player.userID, out var depth)
            && depth > 0;
    }

    private static void SynchronizeDeepSeaVehiclePassengers(DeepSeaVehicleTeleportState state)
    {
        if (state == null || state.Vehicle == null || state.Vehicle.IsDestroyed)
        {
            return;
        }

        foreach (var passenger in state.Passengers)
        {
            var player = passenger.Player;
            if (player == null || !player.IsConnected || player.IsDead())
            {
                continue;
            }

            var targetPosition = state.Vehicle.transform.TransformPoint(passenger.LocalPosition);
            player.Teleport(targetPosition);
            player.UpdateNetworkGroup();
            player.SendNetworkUpdateImmediate();
        }
    }

    private static void RecoverStrandedDeepSeaPassengers(
        DeepSeaVehicleTeleportState state,
        bool shouldBeInsideDeepSea)
    {
        if (state == null
            || state.Vehicle == null
            || state.Vehicle.IsDestroyed
            || DeepSeaManager.IsInsideDeepSea(state.Vehicle) != shouldBeInsideDeepSea)
        {
            return;
        }

        foreach (var passenger in state.Passengers)
        {
            var player = passenger.Player;
            if (player == null
                || !player.IsConnected
                || player.IsDead()
                || DeepSeaManager.IsInsideDeepSea(player) == shouldBeInsideDeepSea)
            {
                continue;
            }

            var recoveryPosition = state.Vehicle.transform.TransformPoint(passenger.LocalPosition);
            player.Teleport(recoveryPosition);
            player.UpdateNetworkGroup();
            player.SendNetworkUpdateImmediate();
            _instance?.PrintWarning(
                "Recovered a DeepSea passenger left behind during "
                + (shouldBeInsideDeepSea ? "entry" : "exit")
                + ": player="
                + player.userID
                + ", vehicle="
                + (state.Vehicle.net != null ? state.Vehicle.net.ID.Value : 0uL));
        }
    }

    [AutoPatch]
    [HarmonyPatch(typeof(DeepSeaManager), "TeleportEntity")]
    private static class TeleportDeepSeaEntityPatch
    {
        [HarmonyPrefix]
        private static bool Prefix(BaseEntity entity, Vector3 position)
        {
            if (!(entity is PlayerBoat boat) || boat.IsDestroyed)
            {
                return true;
            }

            var state = CaptureDeepSeaVehiclePassengers(boat);
            boat.Teleport(position);
            SynchronizeDeepSeaVehiclePassengers(state);
            return false;
        }
    }

    [AutoPatch]
    [HarmonyPatch(typeof(DeepSeaManager), "MoveToDeepSea")]
    private static class MoveToDeepSeaPatch
    {
        [HarmonyPrefix]
        private static void Prefix(BaseEntity entity, ref DeepSeaVehicleTeleportState __state)
        {
            __state = CaptureDeepSeaVehiclePassengers(entity);
            _instance?.BeginDeepSeaTransfer(__state);
        }

        [HarmonyPostfix]
        private static void Postfix(BaseEntity entity, DeepSeaVehicleTeleportState __state)
        {
            RecoverStrandedDeepSeaPassengers(__state, shouldBeInsideDeepSea: true);
        }

        [HarmonyFinalizer]
        private static Exception Finalizer(Exception __exception, DeepSeaVehicleTeleportState __state)
        {
            _instance?.EndDeepSeaTransfer(__state);
            return __exception;
        }
    }

    [AutoPatch]
    [HarmonyPatch(typeof(DeepSeaManager), "MoveToMainIsland")]
    private static class MoveToMainIslandPatch
    {
        [HarmonyPrefix]
        private static void Prefix(BaseEntity entity, ref DeepSeaVehicleTeleportState __state)
        {
            __state = CaptureDeepSeaVehiclePassengers(entity);
            _instance?.BeginDeepSeaTransfer(__state);
        }

        [HarmonyPostfix]
        private static void Postfix(BaseEntity entity, DeepSeaVehicleTeleportState __state)
        {
            RecoverStrandedDeepSeaPassengers(__state, shouldBeInsideDeepSea: false);

            var instance = _instance;
            if (instance == null || __state == null)
            {
                return;
            }

            instance.timer.Once(0.1f, () =>
            {
                if (_instance == instance)
                {
                    RecoverStrandedDeepSeaPassengers(__state, shouldBeInsideDeepSea: false);
                }
            });
        }

        [HarmonyFinalizer]
        private static Exception Finalizer(Exception __exception, DeepSeaVehicleTeleportState __state)
        {
            _instance?.EndDeepSeaTransfer(__state);
            return __exception;
        }
    }

    [AutoPatch]
    [HarmonyPatch(typeof(BaseMountable), "DismountPlayer", typeof(BasePlayer), typeof(bool))]
    private static class DeepSeaTransferDismountPatch
    {
        [HarmonyPrefix]
        private static void Prefix(BasePlayer player, ref bool lite)
        {
            if (_instance?.IsPlayerInDeepSeaTransfer(player) == true)
            {
                lite = true;
            }
        }
    }
}
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху