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

FREE Casino : 0.1.14 0.1.14

Нет прав для скачивания
C#:
using Facepunch;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Globalization;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Plugins;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Casino", "k1lly0u", "0.1.14")]
    [Description("Core card game and table management system")]
    public class Casino : RustPlugin
    {
        #region Fields        
        [PluginReference]
        private Plugin ServerRewards, Economics, ImageLibrary, MonumentFinder;

        private readonly Hash<GameType, Action<BaseEntity, StoredData.GameData>> registeredGames = new Hash<GameType, Action<BaseEntity, StoredData.GameData>>();

        private bool wipeData = false;

        public static Casino Instance { get; private set; }

        public static PlayingCards Images { get; private set; }

        private static List<CardGame> ActiveGames;

        private static readonly KeyValuePair<Vector3, Vector3>[] ChairPositions = new KeyValuePair<Vector3, Vector3>[]
        {
            new KeyValuePair<Vector3, Vector3>(new Vector3(0.5f, 0, -1.25f), new Vector3(0, 0, 0)),
            new KeyValuePair<Vector3, Vector3>(new Vector3(-0.5f, 0, -1.25f), new Vector3(0, 0, 0)),
            new KeyValuePair<Vector3, Vector3>(new Vector3(0.5f, 0, 1.25f), new Vector3(0, 180, 0)),
            new KeyValuePair<Vector3, Vector3>(new Vector3(-0.5f, 0, 1.25f), new Vector3(0, 180, 0))
        };

        private const string CHAIR_PREFAB = "assets/prefabs/deployable/chair/chair.deployed.prefab";

        private const string TABLE_PREFAB = "assets/prefabs/deployable/table/table.deployed.prefab";

        public enum GameType { BlackJack, Roulette, Baccarat }

        public enum GameState { Waiting, PlacingBets, Prestart, Playing }

        public enum BettingType { Item, ServerRewards, Economics }
        #endregion

        #region Oxide Hooks
        private void Loaded()
        {
            Instance = this;

            ActiveGames = new List<CardGame>();            
        }

        protected override void LoadDefaultMessages() => lang.RegisterMessages(new Dictionary<string, string>
        {
            ["Error.NotEnoughAmount"] = "<color=#D3D3D3>You do not have have {0} to play this table.Minimum bet is :</color> <color=#ce422b>{1}</color>",
            ["Table.Information"] = "<size=25>{0}</size><size=20>\nMin Bet: {1} {3}\nMax Bet: {2} {3}\nTake a seat to play!</size>",
            ["Bet.RP"] = "RP",
            ["Bet.Eco"] = "Eco"
        }, this);

        private void OnServerInitialized()
        {
            LoadData();

            if (wipeData)
            {
                storedData.tables.Clear();
                SaveData();
            }

            timer.In(3f, ()=> LoadImages(0));
        }

        private void LoadImages(int attempts = 0)
        {
            if (!ImageLibrary)
            {
                if (attempts > 3)
                {
                    Puts("[Casino] - This plugin requires ImageLibrary to manage the card images.Please install ImageLibrary to continue...");
                    return;
                }

                timer.In(10, () => LoadImages(attempts++));
                return;
            }

            Images = new PlayingCards(ImageLibrary);
            Images.ImportCardImages(registeredGames.Keys, Configuration.ForceUpdate, LoadTables);
        }

        private void OnNewSave(string filename) => wipeData = true;

        private void OnEntityMounted(BaseMountable mountable, BasePlayer player)
        {
            if (!mountable)
                return;

            GameChair gameChair = mountable.GetComponent<GameChair>();
            if (gameChair == null)
                return;

            CardGame cardGame = gameChair.CardGame;
            if (cardGame == null)
                return;

            int position = cardGame.GetChairPosition(mountable);
            if (position == -1)
            {
                PrintError("Player tried mounting a CardGame with a chair position of -1.Perhaps a old chair that was cleaned up properly? Tell k1lly0u");
                return;
            }
            cardGame.OnPlayerEnter(player, position);
            gameChair.OnPlayerEnter(player);
        }

        private object CanMountEntity(BasePlayer player, BaseMountable mountable)
        {
            CardGame cardGame = mountable.GetComponent<GameChair>()?.CardGame;
            if (cardGame != null)
            {
                int amount = cardGame.GetUserAmount(player);
                if (amount < cardGame.Data.minimumBet)
                {
                    SendReply(player, string.Format(lang.GetMessage("Error.NotEnoughAmount", this, player.UserIDString), cardGame.FormatBetString(player), cardGame.Data.minimumBet));
                    return false;
                }
            }
            return null;
        }

        private object CanDismountEntity(BasePlayer player, BaseMountable mountable)
        {
            CardGame cardGame = mountable.GetComponent<GameChair>()?.CardGame;
            if (cardGame != null)
            {
                if (!cardGame.CanDismountStandard())
                {
                    CardPlayer cardPlayer = player.GetComponent<CardPlayer>();
                    if (cardPlayer != null && cardPlayer.IsLeaving)
                        return null;

                    return false;
                }
            }
            return null;
        }

        private void OnEntityDismounted(BaseMountable mountable, BasePlayer player)
        {
            GameChair gameChair = mountable.GetComponent<GameChair>();
            if (gameChair == null)
                return;

            CardGame cardGame = gameChair.CardGame;
            if (cardGame == null)
                return;

            cardGame.OnPlayerExit(player);
            gameChair.OnPlayerExit(player);
        }

        private object OnEntityTakeDamage(BaseMountable baseMountable, HitInfo info)
        {
            if (!baseMountable.IsValid())
                return null;

            if (baseMountable.GetComponent<GameChair>())
                return true;            

            return null;
        }

        private object OnEntityTakeDamage(DecorDeployable decorDeployable, HitInfo info)
        {
            if (!decorDeployable.IsValid())
                return null;

            if (decorDeployable.GetComponent<CardGame>())
                return true;

            return null;
        }

        private object OnEntityTakeDamage(BasePlayer player, HitInfo info)
        {            
            if (player != null && GameFromPlayer(player))
                return true;

            return null;
        }

        private void OnEntityKill(BaseMountable baseMountable)
        {
            GameChair gameChair = baseMountable.GetComponent<GameChair>();
            if (gameChair == null)
                return;

            CardGame cardGame = gameChair.CardGame;
            int number = gameChair.Number;

            timer.In(1f, () =>
            {
                if (cardGame == null)
                    return;

                cardGame.CreateSeat(number);
            });
        }

        private void OnPlayerDisconnected(BasePlayer player)
        {
            CardGame cardGame = GameFromPlayer(player);
            if (cardGame == null)
                return;

            cardGame.OnPlayerExit(player);
        }

        private void Unload()
        {
            Unsubscribe(nameof(OnEntityKill));

            for (int i = 0; i < ActiveGames.Count; i++)            
                UnityEngine.Object.Destroy(ActiveGames[i]);
            
            ActiveGames.Clear();

            Instance = null;
            Images = null;
            Configuration = null;
        }
        #endregion

        #region Game Registration
        public void RegisterGame(GameType gameType, Action<BaseEntity, StoredData.GameData> callback) => registeredGames[gameType] = callback;

        public void UnregisterGame(GameType gameType)
        {
            registeredGames.Remove(gameType);

            for (int i = ActiveGames.Count - 1; i >= 0; i--)
            {
                CardGame cardGame = ActiveGames[i];
                if (cardGame.Type == gameType)
                {
                    ActiveGames.Remove(cardGame);
                    UnityEngine.Object.Destroy(cardGame);                    
                }
            }
        }
        #endregion

        #region Table Restoration
        private void LoadTables()
        {
            List<uint> allTables = storedData.tables.Keys.ToList();

            BaseEntity[] objects = BaseEntity.saveList.Where(x => x is DecorDeployable).ToArray();
            if (objects != null)
            {
                foreach (BaseEntity baseEntity in objects)
                {
                    if (baseEntity == null || !baseEntity.IsValid() || baseEntity.IsDestroyed)
                        continue;

                    if (storedData.IsRegisteredTable(baseEntity.net.ID))
                    {
                        StoredData.GameData gameData = storedData.tables[baseEntity.net.ID];
                        if (registeredGames.ContainsKey(gameData.gameType))
                        {
                            CreateCardGame(baseEntity, gameData);
                            allTables.Remove(baseEntity.net.ID);
                        }
                    }
                }
            }

            bool save = false;
            for (int i = 0; i < allTables.Count; i++)
            {
                uint netId = allTables[i];
                StoredData.GameData gameData = storedData.tables[netId];

                Vector3 position = gameData.Position;
                Quaternion rotation = Quaternion.Euler(gameData.Rotation);

                if (position == Vector3.zero)
                    continue;

                if (!registeredGames.ContainsKey(gameData.gameType))
                {
                    Debug.LogError($"Failed to create card game {gameData.gameType} ({gameData.Position}).Is the respective card game plugin loaded?");
                    continue;
                }

                DecorDeployable tableEntity = GameManager.server.CreateEntity(TABLE_PREFAB, position, rotation) as DecorDeployable;
                DestroyComponents(tableEntity);
                tableEntity.Spawn();

                CreateCardGame(tableEntity, gameData);

                storedData.UpdateTableID(netId, tableEntity.net.ID, gameData);
               
                save = true;
            }

            if (MonumentFinder) 
            {
                foreach (KeyValuePair<string, List<StoredData.GameData>> kvp in storedData.monumentTables)
                {
                    foreach (StoredData.GameData gameData in kvp.Value) 
                    {
                        if (!registeredGames.ContainsKey(gameData.gameType))
                        {
                            Debug.LogError($"Failed to create monument card game {gameData.gameType}.Is the respective card game plugin loaded?");
                            continue;
                        }

                        MonumentAdapter.ApplyToMonumentsOfType(kvp.Key, gameData, CreateMonumentCardGame);                        
                    }
                }
            }

            if (save)
                SaveData();
        }


        #endregion

        #region Game Setup
        private void CreateCardGame(BaseEntity baseEntity, StoredData.GameData gameData)
        {
            if (!registeredGames.ContainsKey(gameData.gameType))
            {
                Debug.LogError($"Failed to create card game {gameData.gameType} ({gameData.Position}).Is the respective card game plugin loaded?");
                return;
            }

            DestroyComponents(baseEntity);
            
            registeredGames[gameData.gameType].Invoke(baseEntity, gameData);
        }

        private void CreateMonumentCardGame(string shortname, StoredData.GameData gameData, MonumentAdapter monumentAdapter)
        {
            DecorDeployable tableEntity = GameManager.server.CreateEntity(TABLE_PREFAB, 
                monumentAdapter.WorldPositionFromTransform(gameData.Position), 
                monumentAdapter.WorldRotationFromTransform(Quaternion.Euler(gameData.Rotation))) as DecorDeployable;

            DestroyComponents(tableEntity);

            tableEntity.enableSaving = false;
            tableEntity.Spawn();

            CreateCardGame(tableEntity, gameData);

            CardGame cardGame = tableEntity.GetComponent<CardGame>();
            cardGame.RegisteredToMonument = shortname;
        }

        private static BaseMountable CreateSeatEntity(BaseEntity entity, int number, CardGame cardgame)
        {
            Vector3 position = entity.transform.position + (entity.transform.rotation * ChairPositions[number].Key);
            Quaternion rotation = entity.transform.rotation * Quaternion.Euler(ChairPositions[number].Value);

            BaseMountable baseMountable = GameManager.server.CreateEntity(CHAIR_PREFAB, position, rotation) as BaseMountable;
            baseMountable.enableSaving = false;
            baseMountable.canWieldItems = false;
            baseMountable.pickup.enabled = false;
            baseMountable.skinID = Configuration.ChairSkinID;

            DestroyComponents(baseMountable);

            baseMountable.Spawn();

            baseMountable.gameObject.AddComponent<GameChair>().SetCardGame(cardgame, number);
            return baseMountable;
        }
        #endregion

        #region Helpers
        private CardGame GameFromPlayer(BasePlayer player)
        {
            CardPlayer cardPlayer = player.GetComponent<CardPlayer>();
            if (cardPlayer == null)
                return null;

            return cardPlayer.CardGame;
        }

        private BaseEntity FindEntityFromRay(BasePlayer player)
        {
            Ray ray = new Ray(player.eyes.position, Quaternion.Euler(player.serverInput.current.aimAngles) * Vector3.forward);
            RaycastHit hit;
            if (!Physics.Raycast(ray, out hit, 3f))
                return null;

            BaseEntity hitEnt = hit.collider.GetComponentInParent<BaseEntity>();
            if (hitEnt != null)
                return hitEnt;
            return null;
        }

        private static void DestroyComponents(BaseEntity baseEntity)
        {
            BaseCombatEntity baseCombatEntity = baseEntity as BaseCombatEntity;
            if (baseCombatEntity != null)            
                baseCombatEntity.pickup.enabled = false;
            
            DecayEntity decayEntity = baseEntity as DecayEntity;
            if (decayEntity != null)
                decayEntity.decay = null;

            StabilityEntity stabilityEntity = baseEntity as StabilityEntity;
            if (stabilityEntity != null)
            {
                stabilityEntity.grounded = true;
                stabilityEntity.cachedStability = 1f;
                stabilityEntity.cachedDistanceFromGround = 1;
            }

            UnityEngine.Object.Destroy(baseEntity.GetComponent<DestroyOnGroundMissing>());
            UnityEngine.Object.Destroy(baseEntity.GetComponent<GroundWatch>());
        }

        private static T ParseType<T>(string type)
        {
            try
            {
                T value = (T)Enum.Parse(typeof(T), type, true);
                if (Enum.IsDefined(typeof(T), value))
                    return value;
            }
            catch
            {                
                return default(T);
            }
            return default(T);
        }
        #endregion        

        #region Base Game
        public class CardGame : MonoBehaviour
        {
            public DecorDeployable Table { get; private set; }

            public StoredData.GameData Data { get; private set; }

            public TimerElement Timer { get; private set; }

            public TableInformer Informer { get; private set; }

            public GameState State { get; set; } = GameState.Waiting;

            public CardPlayer[] Players { get; private set; }

            private BaseMountable[] Seats { get; set; }

            public string RegisteredToMonument { get; set; }

            public virtual GameType Type { get; }

            public void Awake()
            {
                Table = GetComponent<DecorDeployable>();
                Timer = gameObject.AddComponent<TimerElement>();
                Informer = gameObject.AddComponent<TableInformer>();

                enabled = false;
            }

            public virtual void OnDestroy()
            {
                Destroy(Informer);

                for (int i = 0; i < Players.Length; i++)
                {
                    CardPlayer cardPlayer = Players[i];
                    if (cardPlayer != null)
                        Destroy(cardPlayer);
                }

                for (int i = Seats.Length - 1; i >= 0; i--)
                {
                    BaseMountable baseMountable = Seats[i];
                    if (baseMountable != null)
                    {
                        baseMountable.DismountAllPlayers();
                        baseMountable.Kill(BaseNetworkable.DestroyMode.None);
                    }
                }

                Destroy(Timer);

                if (!string.IsNullOrEmpty(RegisteredToMonument) && Table != null && !Table.IsDestroyed)                
                    Table.Kill(BaseNetworkable.DestroyMode.None);                
            }

            public void SetTableSkinID(ulong skinID)
            {
                if (Table.skinID == skinID || skinID == 0UL)
                    return;

                Table.skinID = skinID;
                Table.SendNetworkUpdateImmediate();

                Table.ClientRPC<int, uint>(null, "Client_ReskinResult", 1, Table.net.ID);
            }

            #region Game Initialization
            public void InitializeGame(StoredData.GameData gameData)
            {
                Data = gameData;
                Data.InitializeBetData();

                Players = new CardPlayer[gameData.maxPlayers];
                Seats = new BaseMountable[gameData.maxPlayers];

                for (int i = 0; i < gameData.maxPlayers; i++)
                    CreateSeat(i);

                OnGameInitialized();
            }

            public void CreateSeat(int number) => Seats[number] = CreateSeatEntity(Table, number, this);

            public virtual void OnGameInitialized()
            {
                Informer.OnGameInitialized();

                ActiveGames.Add(this);
            }
            #endregion

            public virtual void OnPlayerEnter(BasePlayer player, int position) { }

            public virtual void OnPlayerExit(BasePlayer player) { }

            public virtual bool CanDismountStandard() => false;

            public int GetChairPosition(BaseMountable baseMountable)
            {
                for (int i = 0; i < Seats.Length; i++)
                {
                    if (Seats[i].EqualNetID(baseMountable))
                        return i;
                }
                return -1;
            }

            public int CurrentPlayerCount
            {
                get
                {
                    int count = 0;
                    for (int i = 0; i < Players.Length; i++)
                    {
                        if (Players[i] != null)
                            count++;
                    }
                    return count;
                }
            }

            public int CurrentPlayingCount
            {
                get
                {
                    int count = 0;
                    for (int i = 0; i < Players.Length; i++)
                    {
                        if (Players[i] != null && Players[i].IsPlaying)
                            count++;
                    }
                    return count;
                }
            }

            #region Betting  
            public void AdjustBet(CardPlayer cardPlayer, int amount, int minimum, int maximum)
            {
                if (State != GameState.PlacingBets)
                    return;

                amount = Mathf.Clamp(amount + cardPlayer.BetAmount, minimum, maximum);
                if (cardPlayer.BankBalance < amount)
                    return;

                cardPlayer.BetAmount = amount;
            }

            public void ResetBet(CardPlayer cardPlayer)
            {
                if (State != GameState.PlacingBets)
                    return;

                cardPlayer.BetAmount = Data.minimumBet;
            }

            public int GetUserAmount(BasePlayer player)
            {
                switch (Data.BetType)
                {
                    case BettingType.Item:
                        return player.inventory.GetAmount(Data.BetItemID);
                    case BettingType.ServerRewards:
                        return (int)Instance.ServerRewards?.Call("CheckPoints", player.userID);
                    case BettingType.Economics:
                        return Convert.ToInt32((double)Instance.Economics?.Call("Balance", player.UserIDString));
                }
                return 0;
            }

            public void TakeAmount(BasePlayer player, int amount)
            {
                switch (Data.BetType)
                {
                    case BettingType.Item:
                        player.inventory.Take(null, Data.BetItemID, amount);
                        break;
                    case BettingType.ServerRewards:
                        Instance.ServerRewards?.Call("TakePoints", player.userID, amount);
                        break;
                    case BettingType.Economics:
                        Instance.Economics?.Call("Withdraw", player.UserIDString, (double)amount);
                        break;
                }
            }

            public void GiveAmount(BasePlayer player, int amount)
            {
                switch (Data.BetType)
                {
                    case BettingType.Item:
                        Item item = ItemManager.CreateByItemID(Data.BetItemID, amount);
                        player.inventory.GiveItem(item, null);
                        break;
                    case BettingType.ServerRewards:
                        Instance.ServerRewards?.Call("AddPoints", player.userID, amount);
                        break;
                    case BettingType.Economics:
                        Instance.Economics?.Call("Deposit", player.UserIDString, (double)amount);
                        break;
                }
            }

            public string FormatBetString(BasePlayer player = null)
            {
                switch (Data.BetType)
                {
                    case BettingType.Item:
                        return Data.BetItemName;
                    case BettingType.ServerRewards:
                        return Instance.lang.GetMessage("Bet.RP", Instance, player?.UserIDString);
                    case BettingType.Economics:
                        return Instance.lang.GetMessage("Bet.Eco", Instance, player?.UserIDString);
                }
                return string.Empty;
            }
            #endregion
        }
        #endregion

        #region Game Chair
        public class GameChair : MonoBehaviour
        {
            private BaseMountable mountable;

            private TriggerSafeZone triggerSafeZone;

            public CardGame CardGame { get; private set; }

            public int Number { get; private set; }

            private BasePlayer mounted;

            private const int PLAYER_MASK = 131072;

            private void Awake()
            {
                mountable = GetComponent<BaseMountable>();

                enabled = false;

                if (!IsInSafeZone(transform.position) && Configuration.ChairSafeZone)
                {
                    triggerSafeZone = gameObject.AddComponent<TriggerSafeZone>();
                    triggerSafeZone.interestLayers = PLAYER_MASK;
                    triggerSafeZone.enabled = false;
                }
            }

            private void OnDestroy()
            {
                if (triggerSafeZone)
                {
                    if (triggerSafeZone.entityContents != null)
                    {
                        for (int i = triggerSafeZone.entityContents.Count - 1; i >= 0; i--)
                        {
                            BaseEntity baseEntity = triggerSafeZone.entityContents.ElementAt(i);
                            if (baseEntity)
                            {
                                triggerSafeZone.entityContents.Remove(baseEntity);
                                baseEntity.LeaveTrigger(triggerSafeZone);
                            }
                        }
                    }

                    if (mounted != null && mounted.IsConnected)
                    {
                        if (triggerSafeZone != null)
                            mounted.LeaveTrigger(triggerSafeZone);
                    }

                    Destroy(triggerSafeZone);
                }
            }

            public void SetCardGame(CardGame cardGame, int number)
            {
                this.CardGame = cardGame;
                this.Number = number;
            }

            public void OnPlayerEnter(BasePlayer player)
            {
                mounted = player;

                if (triggerSafeZone)
                {
                    if (triggerSafeZone.entityContents == null)
                        triggerSafeZone.entityContents = new HashSet<BaseEntity>();

                    if (!triggerSafeZone.entityContents.Contains(player))
                    {
                        triggerSafeZone.entityContents.Add(player);
                        player.EnterTrigger(triggerSafeZone);

                        if (player.IsItemHoldRestricted(player.inventory.containerBelt.FindItemByUID(player.svActiveItemID)))
                            player.UpdateActiveItem(0);

                        player.SetPlayerFlag(BasePlayer.PlayerFlags.SafeZone, true);
                    }
                }
            }

            public void OnPlayerExit(BasePlayer player)
            {
                if (triggerSafeZone)
                {
                    if (triggerSafeZone.entityContents != null && triggerSafeZone.entityContents.Contains(player))
                        triggerSafeZone.entityContents.Remove(player);

                    if (triggerSafeZone != null)
                        player.LeaveTrigger(triggerSafeZone);

                    player.SetPlayerFlag(BasePlayer.PlayerFlags.SafeZone, false);

                    mounted = null;
                }
            }

            private static bool IsInSafeZone(Vector3 position)
            {
                int count = Physics.OverlapSphereNonAlloc(position, 1f, Vis.colBuffer, 1 << 18, QueryTriggerInteraction.Collide);
                for (int i = 0; i < count; i++)
                {
                    Collider collider = Vis.colBuffer[i];
                    if (collider.GetComponent<TriggerSafeZone>())
                        return true;
                }

                return false;
            }
        }
        #endregion

        #region Table Informer
        public class TableInformer : MonoBehaviour
        {
            private DecorDeployable table;

            private CardGame cardGame;

            private OBB worldSpaceBounds;

            private Vector3 drawPosition;

            private string informationStr;

            private const float REFRESH_RATE = 2f;

            private void Awake()
            {
                table = GetComponent<DecorDeployable>();

                cardGame = GetComponent<CardGame>();

                drawPosition = transform.position + (Vector3.up * 1.5f);

                Bounds bounds = table.bounds;
                bounds.Expand(Configuration.DDrawBoundsMultiplier);

                worldSpaceBounds = new OBB(transform.position, transform.lossyScale, transform.rotation, bounds);                 
            }

            public void OnGameInitialized()
            {
                informationStr = string.Format(Instance.lang.GetMessage("Table.Information", Instance), cardGame.Data.gameType, cardGame.Data.minimumBet, cardGame.Data.maximumBet, cardGame.FormatBetString());

                InvokeHandler.InvokeRepeating(this, InformationTick, UnityEngine.Random.Range(0.1f, 2f), REFRESH_RATE);
            }

            private void InformationTick()
            {               
                List<BasePlayer> basePlayers = Pool.GetList<BasePlayer>();
                Vis.Entities(worldSpaceBounds, basePlayers);
                for (int i = 0; i < basePlayers.Count; i++)
                {
                    BasePlayer player = basePlayers[i];
                    if (player == null || player.IsDead() || player.isMounted)
                        continue;

                    if (player.IsAdmin)
                        player.SendConsoleCommand("ddraw.text", REFRESH_RATE, Color.white, drawPosition, informationStr);
                    else
                    {
                        player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
                        player.SendNetworkUpdateImmediate();
                        player.SendConsoleCommand("ddraw.text", REFRESH_RATE, Color.white, drawPosition, informationStr);
                        player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, false);
                        player.SendNetworkUpdateImmediate();
                    }
                }

                Pool.FreeList(ref basePlayers);
            }
        }
        #endregion

        #region Game Timer
        public class TimerElement : MonoBehaviour
        {
            public Casino.CardGame CardGame { get; private set; }

            private int timeRemaining;

            private Action callback;

            private const string TIMER_OVERLAY = "casino.timer";

            private UI4 TIMER_POSITION = new UI4(0.475f, 0f, 0.525f, 0.05f);

            private void Awake() => CardGame = GetComponent<Casino.CardGame>();

            public void StartTimer(int time, Action callback = null)
            {
                this.timeRemaining = time + 1;

                this.callback = callback;

                InvokeHandler.InvokeRepeating(this, TimerTick, 0f, 1f);
            }

            public void StopTimer()
            {
                if (!InvokeHandler.IsInvoking(this, TimerTick))
                    return;

                InvokeHandler.CancelInvoke(this, TimerTick);

                for (int i = 0; i < CardGame.Players.Length; i++)
                {
                    CardPlayer cardPlayer = CardGame.Players[i];
                    if (cardPlayer == null)
                        continue;

                    cardPlayer.DestroyUI(TIMER_OVERLAY);
                }
            }

            private void TimerTick()
            {
                timeRemaining--;

                if (timeRemaining == 0)
                {
                    StopTimer();
                    callback?.Invoke();
                }
                else UpdateTimerUI();
            }

            private void UpdateTimerUI()
            {
                CuiElementContainer container = UI.Container(TIMER_OVERLAY, TIMER_POSITION);
                UI.Label(container, TIMER_OVERLAY, $"{timeRemaining}", 18, UI4.FullScreen);

                for (int i = 0; i < CardGame.Players.Length; i++)
                {
                    CardPlayer cardPlayer = CardGame.Players[i];
                    if (cardPlayer == null)
                        continue;

                    cardPlayer.AddUI(TIMER_OVERLAY, container);
                }
            }
        }
        #endregion

        #region Card Player
        public class CardPlayer : MonoBehaviour
        {            
            public List<Card> hand = Pool.GetList<Card>();

            public List<string> uiPanels = Pool.GetList<string>();

            public BasePlayer Player { get; private set; }

            public Casino.CardGame CardGame { get; set; }

            public bool IsLeaving { get; private set; }

            public int UID { get; private set; }

            public int BetAmount { get; set; }

            public bool BetLocked { get; set; }

            public bool IsPlaying { get; set; } = false;

            public int Position { get; set; }

            public virtual int BankBalance
            {
                get
                {
                    return CardGame.GetUserAmount(Player);
                }
            }

            public int BalanceAndBet
            {
                get
                {
                    return BankBalance + BetAmount;
                }
            }

            public virtual void Awake()
            {
                Player = GetComponent<BasePlayer>();
                CardGame = Player.GetMounted().GetComponent<Casino.GameChair>().CardGame;
                BetAmount = CardGame.Data.minimumBet;

                GenerateUID();
                enabled = false;
            }

            public virtual void OnDestroy()
            {
                IsLeaving = true;

                DestroyUI();

                if (Player.isMounted)
                {
                    Player.GetMounted().DismountPlayer(Player, false);
                }

                Pool.FreeList(ref hand);
                Pool.FreeList(ref uiPanels);
            }

            public void GenerateUID() => UID = UnityEngine.Random.Range(int.MinValue, int.MaxValue);

            public virtual void ResetHand()
            {
                hand.Clear();
                BetAmount = CardGame.Data.minimumBet;
                BetLocked = false;
                IsPlaying = false;
            }

            public virtual void SetBet()
            {
                BetLocked = true;
                CardGame.TakeAmount(Player, BetAmount);                
            }

            public void IssueWin(int amount)
            {
                CardGame.GiveAmount(Player, amount);               
            }

            public void AddUI(string str, CuiElementContainer container)
            {
                DestroyUI(str);
                uiPanels.Add(str);                   
                CuiHelper.AddUi(Player, container);
            }

            public virtual void DestroyUI(string str)
            {
                uiPanels.Remove(str);
                CuiHelper.DestroyUi(Player, str);
            }

            public virtual void DestroyUI()
            {
                foreach (string str in uiPanels)                
                    CuiHelper.DestroyUi(Player, str);                

                uiPanels.Clear();
            }
        }
        #endregion

        #region Deck Of Cards
        public class Deck
        {
            private readonly Queue<Card> _deck = new Queue<Card>();

            private readonly List<int> _cardIndexes = new List<int>();

            private readonly System.Random _random = new System.Random();

            public Deck()
            {
                IndexCards();
                Shuffle();
            }

            private void IndexCards()
            {
                _cardIndexes.Clear();

                for (int i = 0; i < 52; i++)                
                    _cardIndexes.Add(i);                
            }

            public void Shuffle()
            {
                _deck.Clear();                

                for (int i = 51; i >= 0; i--)
                {
                    int index = _random.Next(0, i);
                    int temp = _cardIndexes[i];
                    _cardIndexes[i] = _cardIndexes[index];
                    _cardIndexes[index] = temp;
                }

                Fill();
            }

            private void Fill()
            {
                for (int i = 0; i < _cardIndexes.Count; i++)
                {
                    CardSuit suit = (CardSuit)(_cardIndexes[i] % 4);
                    CardValue value = (CardValue)(_cardIndexes[i] % 13 + 1);

                    _deck.Enqueue(new Card(suit, value));
                }
            }

            public Card Deal() => _deck.Dequeue();            
        }

        public struct Card
        {
            public CardSuit Suit { get; private set; }

            public CardValue Value { get; private set; }

            private string ImageID { get; set; }

            public Card(CardSuit suit, CardValue value) : this()
            {
                this.Suit = suit;
                this.Value = value;
                this.ImageID = string.Empty;
            }

            public override string ToString() => string.Format("Suit: {0}, Value: {1}", this.Suit, this.Value);

            public string GetCardImage()
            {
                if (string.IsNullOrEmpty(ImageID))
                {
                    string value = string.Empty;
                    string suit = string.Empty;

                    switch (Value)
                    {
                        case CardValue.Ace:
                            value = "A";
                            break;
                        case CardValue.Deuce:
                        case CardValue.Three:
                        case CardValue.Four:
                        case CardValue.Five:
                        case CardValue.Six:
                        case CardValue.Seven:
                        case CardValue.Eight:
                        case CardValue.Nine:
                        case CardValue.Ten:
                            value = ((int)Value).ToString();
                            break;
                        case CardValue.Jack:
                            value = "J";
                            break;
                        case CardValue.Queen:
                            value = "Q";
                            break;
                        case CardValue.King:
                            value = "K";
                            break;
                    }

                    switch (Suit)
                    {
                        case CardSuit.Spades:
                            suit = "S";
                            break;
                        case CardSuit.Diamonds:
                            suit = "D";
                            break;
                        case CardSuit.Hearts:
                            suit = "H";
                            break;
                        case CardSuit.Clubs:
                            suit = "C";
                            break;
                    }

                    ImageID = Images.GetCardImage(value, suit);
                }

                return ImageID;
            }
        }
        
        public enum CardSuit
        {
            Spades = 0,
            Diamonds = 1,
            Hearts = 2,
            Clubs = 3
        }

        public enum CardValue
        {
            Ace = 1,
            Deuce = 2,
            Three = 3,
            Four = 4,
            Five = 5,
            Six = 6,
            Seven = 7,
            Eight = 8,
            Nine = 9,
            Ten = 10,
            Jack = 11,
            Queen = 12,
            King = 13
        }
        #endregion

        #region UI     
        public static class UI
        {            
            public static CuiElementContainer Container(string panel, UI4 dimensions, bool useCursor = false, string parent = "Overlay")
            {
                CuiElementContainer container = new CuiElementContainer()
                {
                    {
                        new CuiPanel
                        {
                            Image = {Color = "0 0 0 0"},
                            RectTransform = {AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()},
                            CursorEnabled = useCursor
                        },
                        new CuiElement().Parent = parent,
                        panel
                    }
                };
                return container;
            }

            public static void Panel(CuiElementContainer container, string panel, string color, UI4 dimensions, bool blur = false)
            {
                container.Add(new CuiPanel
                {
                    Image = { Color = color, Material = blur ? "assets/content/ui/uibackgroundblur-ingamemenu.mat" : string.Empty },
                    RectTransform = { AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax() }
                },
                panel);
            }

            public static void Label(CuiElementContainer container, string panel, string text, int size, UI4 dimensions, TextAnchor align = TextAnchor.MiddleCenter)
            {
                container.Add(new CuiLabel
                {
                    Text = { FontSize = size, Align = align, Text = text },
                    RectTransform = { AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax() }
                },
                panel);
            }

            public static void OutlinedLabel(CuiElementContainer container, string panel, string text, int size, UI4 dimensions, TextAnchor align = TextAnchor.MiddleCenter)
            {
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = panel.ToString(),
                    FadeOut = 0.2f,
                    Components =
                    {
                        new CuiTextComponent
                        {
                            Text = text,
                            FontSize = size,
                            Align = align,
                            FadeIn = 0.2f
                        },
                        new CuiOutlineComponent
                        {
                            Distance = "1 1",
                            Color = Color("000000", 0.7f)
                        },
                        new CuiRectTransformComponent
                        {
                            AnchorMin = dimensions.GetMin(),
                            AnchorMax = dimensions.GetMax()
                        }
                    }
                });
            }

            public static void Button(CuiElementContainer container, string panel, string color, string text, int size, UI4 dimensions, string command, TextAnchor align = TextAnchor.MiddleCenter)
            {
                container.Add(new CuiButton
                {
                    Button = { Color = color, Command = command, FadeIn = 0f },
                    RectTransform = { AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax() },
                    Text = { Text = text, FontSize = size, Align = align }
                },
                panel);
            }

            public static void Button(CuiElementContainer container, string panel, UI4 dimensions, string command)
            {
                container.Add(new CuiButton
                {
                    Button = { Color = "0 0 0 0", Command = command, FadeIn = 0f },
                    RectTransform = { AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax() },
                    Text = { Text = string.Empty, FontSize = 0, Align = TextAnchor.LowerCenter }
                },
                panel);
            }

            public static void Image(CuiElementContainer container, string panel, string png, UI4 dimensions)
            {
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = panel,
                    Components =
                    {
                        new CuiRawImageComponent {Png = png },
                        new CuiRectTransformComponent {AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax() }
                    }
                });
            }

            public static string Color(string hexColor, float alpha)
            {
                if (hexColor.StartsWith("#"))
                    hexColor = hexColor.Substring(1);
                int red = int.Parse(hexColor.Substring(0, 2), NumberStyles.AllowHexSpecifier);
                int green = int.Parse(hexColor.Substring(2, 2), NumberStyles.AllowHexSpecifier);
                int blue = int.Parse(hexColor.Substring(4, 2), NumberStyles.AllowHexSpecifier);
                return $"{(double)red / 255} {(double)green / 255} {(double)blue / 255} {alpha}";
            }
        }

        public class UI4
        {
            public float xMin, yMin, xMax, yMax;

            public UI4(float xMin, float yMin, float xMax, float yMax)
            {
                this.xMin = xMin;
                this.yMin = yMin;
                this.xMax = xMax;
                this.yMax = yMax;
            }

            public string GetMin() => $"{xMin} {yMin}";
            public string GetMax() => $"{xMax} {yMax}";

            private static readonly UI4 _fullScreen = new UI4(0, 0, 1, 1);

            private static readonly UI4 _zero = new UI4(0, 0, 0, 0);

            public static UI4 FullScreen { get { return _fullScreen; } }

            public static UI4 Zero { get { return _zero; } }
        }
        #endregion

        #region Commands
        [ChatCommand("casino")]
        private void cmdCasino(BasePlayer player, string command, string[] args)
        {
            if (!player.IsAdmin)
                return;

            if (args.Length == 0)
            {
                SendReply(player, "<color=#ce422b>/casino create <type> <maximum players> <minimum bet> <maximum bet></color> - Creates the specified type of card game, with the details provided");
                SendReply(player, "<color=#ce422b>/casino createmon <type> <maximum players> <minimum bet> <maximum bet></color> - Creates the specified type of card game, registered to the closest monument");
                SendReply(player, $"Available Games : {registeredGames.Keys.ToSentence()}");
                SendReply(player, "<color=#ce422b>/casino setbet <type> <opt:shortname></color> - Sets the bet type for the car
// ... [Code preview truncated due to length. Full source in attached file] ...

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

Другие ресурсы пользователя 15FPS

Сверху