Помогите Нужна помощь новичку, пишу плагин ...

pagan

21 Фев 2023
94
10
17
Друзья я начинающий плагописец :)) прошу строго не судить, очень нужна ваша помощь
в плагине необходимо создать невидимый контейнер, открыть его вместе с инвентарём игрока,
переложить в него лут (это камень дерево и фрагменты металла) и при закрытии записать в дата файл,
при повторном открытии взять данные из дата файла и положить опять в контейнер (не инвентарь)
И вроде задача простая но я не понимаю куда копать и что делать уже неделю бьюсь пересмотрел чужие плагины
прочитал кучу манов, как создавать объект понял но дальше полный тупик...
C#:
    public class test : RustPlugin
    {
        //Это кнопка
        string Gui_ButBack = "[{\"name\":\"Bootionhorse\",\"parent\":\"Overlay\",\"components\":[{\"type\":\"UnityEngine.UI.Image\",\"material\":\"\",\"color\":\"1 0 0 0.3492877\"},{\"type\":\"RectTransform\",\"anchormin\":\"0.65 0.02333333\",\"anchormax\":\"0.835625 0.1477778\",\"offsetmin\":\"0 0\",\"offsetmax\":\"0 0\"}]},{\"name\":\"BtnBack\",\"parent\":\"Bootionhorse\",\"components\":[{\"type\":\"UnityEngine.UI.Button\",\"command\":\"Closebox\",\"color\":\"0 0 0 0.8352941\"},{\"type\":\"RectTransform\",\"anchormin\":\"0.02356893 0.02999994\",\"anchormax\":\"0.9831649 0.9642856\",\"offsetmin\":\"0 0\",\"offsetmax\":\"0 0\"}]},{\"name\":\"txtBootBack\",\"parent\":\"BtnBack\",\"components\":[{\"type\":\"UnityEngine.UI.Text\",\"text\":\"NEXT\",\"fontSize\":24,\"align\":\"MiddleCenter\"},{\"type\":\"RectTransform\",\"anchormin\":\"0.03521138 0.2199999\",\"anchormax\":\"0.9788731 0.8999999\",\"offsetmin\":\"0 0\",\"offsetmax\":\"0 0\"}]}]";

        //Создать и открыть ящик по команде
        [ChatCommand("opbox")]//opbox
        private void openbox(BasePlayer player)
        {

            var pos = new Vector3(player.transform.position.x, player.transform.position.y - 1, player.transform.position.z);
            string box = "assets/prefabs/deployable/woodenbox/woodbox_deployed.prefab";
            var view = GameManager.server.CreateEntity(box, pos) as StorageContainer;
            view.GetComponent<GroundWatch>().enabled = true;
            //Просто игрался с параметрами
            if (!view) return;
            view.limitNetworking = true;
            view.transform.position = pos;
            view.OwnerID = player.userID;
            view.name = "mybox";
            view.maxStackSize = 4;
            view.inventorySlots = 30;
            view.enableSaving = true;
            view.buildingID = 123456789;
            view.Spawn();
            //view.inventory.entityOwner = view;
            CuiHelper.AddUi(player, Gui_ButBack);
            timer.In(0.1f, delegate ()
            {
                view.PlayerOpenLoot(player);
            });

        //По нажатию кнопки закрыть инвентарь и записать положенный лут в дата файл
        //А именно фрагменты метала, дерево, камень = название и количесво
        }
        private BaseEntity FindBox(string boxNameOrId)
        {
            // Не работает уже не знаю как ((
            BaseEntity box = BaseNetworkable.serverEntities.Find(e => e.name.Contains(boxNameOrId));
            if (box != null)
            {
                return box;
            }

            uint boxId;
            if (uint.TryParse(boxNameOrId, out boxId))
            {
                box = BaseNetworkable.serverEntities.Find(e => e.net.ID == boxId);
            }

            return box;
        }
Заранее спасибо за помощь..
 
зачем ты вставляешь сюда ответы от гпт?
Простите за путаницу, мои ответы иногда могут повторять информацию из предыдущих сообщений. Если у вас есть еще вопросы или нужна помощь, не стесняйтесь спрашивать!
 
Опиши свой класс взаимодействия с дата файлом, там сделай метод преобразующий твой список предметов из этого бокса в список объектов класса (назовем его PluginItem), а так же метод образования предметов из списка сохраненных объектов класса PluginItem. при закрытии сохраняй дата файл в виде словаря, где ключ это steamID игрока а value это List<PluginItem>,
при повторном открытии используй созданный ранее метод для образования предметов в созданном новом боксе.
---
Не обязательно привязывать игрока к какому-то определенному ящику, ты можешь его создавать при взаимодействии и удалять сразу после закрытия (используй для этого хуки oxide)
(это вкратце, я многое опустил)
Я думал об этом, я про это и говорил, вот смотри, открыл загрузил из дата туда ресурсы, всё функция закончена, игрок положил в контейнер что ему нужно и жмёт кнопку закрыть, но объекта в новой функции у меня уже нет, я не могу к нему обратится что бы прочитать данные... в остальном всё правильно, я даже планировал удалять его и создавать новый при открытии... Я ещё не нашёл крючок закрытия инвентаря, ведь закрыть он может и по экскейпу .. Но это не тема этого форума .. Но спасибо за ответ :)
 
Попробуй использовать уникальный идентификатор или имя для поиска контейнера при повторном открытии. В твоем случае, когда создаешь контейнер, задай ему уникальное имя, которое будет использоваться для его последующего поиска и открытия. Например, можно использовать имя игрока и уникальный идентификатор контейнера вместе. При открытии контейнера снова, найди его по этому имени и уникальному идентификатору, затем открой его содержимое. Надеюсь, это поможет тебе справиться с проблемой!
Я и пишу что не знаю как его найти, имя я в черновом варианте даю ему, но не понимаю как сделать find :(
 
  • Мне нравится
Реакции: pagan
у игрока такой контейнер должен быть один?
Да планировал очень просто, игрок открывает, создаётся контейнер всё это открывается в инвентаре игрока (это сделано и работает) после этого он кладёт туда ресурсы закрывает (тоже работает но при закрытии это новая функция и там уже нет объекта а как его найти что бы прочитать что там изменилось, я не понимаю) после этого объект ящика удаляется... Я уже голову сломал, думаю пойду другим путём и буду работать с инвентарём из интерфейса плагина, хотя это увеличит код и будет по моему мнению очень не удобно...
 
Сделай как в backpack по кнопке, типо когда ящик открываешь кнопку "открыть доп слоты " и там будет открывать рюкзак но в ящике
Так сделано это уже :)) Я не могу с ним взаимодействовать при закрытии и банк и рюкзак смотрел но я писал что начинающий, и не понимаю как это делается, хотя всё пересмотрел даже к тебе обращался CHAT GPT! :)))))))) Ты то мне и выдал
C#:
BaseEntity box = BaseNetworkable.serverEntities.Find(e => e.name.Contains(boxNameOrId));
Но оно не работает :)))))))
 
Так сделано это уже :)) Я не могу с ним взаимодействовать при закрытии и банк и рюкзак смотрел но я писал что начинающий, и не понимаю как это делается, хотя всё пересмотрел даже к тебе обращался CHAT GPT! :)))))))) Ты то мне и выдал
C#:
BaseEntity box = BaseNetworkable.serverEntities.Find(e => e.name.Contains(boxNameOrId));
Но оно не работает :)))))))
Извините за возможные путаницу и сложности в разработке. Попробуйте использовать следующий метод для поиска контейнера при закрытии:

C#:
BaseEntity box = BaseNetworkable.serverEntities.Find(e => e.name == boxNameOrId && e.OwnerID == player.userID);

Здесь boxNameOrId - это уникальное имя или идентификатор контейнера, а player.userID - это идентификатор игрока, который владеет контейнером. Помимо этого, убедитесь, что идентификаторы правильно сравниваются и подходят для вашего случая.

Если у вас возникнут дополнительные вопросы или проблемы, не стесняйтесь обращаться за помощью!
 
Извините за возможные путаницу и сложности в разработке. Попробуйте использовать следующий метод для поиска контейнера при закрытии:

C#:
BaseEntity box = BaseNetworkable.serverEntities.Find(e => e.name == boxNameOrId && e.OwnerID == player.userID);

Здесь boxNameOrId - это уникальное имя или идентификатор контейнера, а player.userID - это идентификатор игрока, который владеет контейнером. Помимо этого, убедитесь, что идентификаторы правильно сравниваются и подходят для вашего случая.

Если у вас возникнут дополнительные вопросы или проблемы, не стесняйтесь обращаться за помощью!
:))))))))))))))))))))))))))))
Error while compiling teect: Cannot convert lambda expression to type 'NetworkableId' because it is not a delegate type
 
BaseEntity box = BaseNetworkable.serverEntities.Find(e => e.name.Contains(boxNameOrId));
e.name это название, пробывал хотя бы вывести что это в консоль?
Там скорее всего будет container или что то в этом роде.

Тебе нужен net id контейнера.
Примерная логика, с обработкой возможных ошибок и как дописать - думаю сам разберешся.
C#:
        private Dictionary<ulong, ulong> _playerContainers;
        private StorageContainer GetContainer(BasePlayer player)
        {
            if(_playerContainers.ContainsKey(player.userID))
                return FindExistContainer(_playerContainers[player.userID]);
            else
            {
                StorageContainer container = CreateContainer(player);

                _playerContainers.Add(player.userID, container.net.ID.Value);
           
                return container;
            }

        }
        private StorageContainer FindExistContainer(ulong id)
            => BaseNetworkable.serverEntities.SingleOrDefault(x => x.net.ID.Value == id) as StorageContainer;
        private StorageContainer CreateContainer(BasePlayer player)
        {
            //логика создания контейнера
            return new StorageContainer();
        }
 
  • Мне нравится
Реакции: pagan
или как вариант немного логику переписать, и как игрок заходит сразу получать контейнер и ложить его в словарик в value, чтобы не делать вечный поиск по 100к энтити, а только один раз при заходе
 
Я думал об этом, я про это и говорил, вот смотри, открыл загрузил из дата туда ресурсы, всё функция закончена, игрок положил в контейнер что ему нужно и жмёт кнопку закрыть, но объекта в новой функции у меня уже нет, я не могу к нему обратится что бы прочитать данные... в остальном всё правильно, я даже планировал удалять его и создавать новый при открытии... Я ещё не нашёл крючок закрытия инвентаря, ведь закрыть он может и по экскейпу .. Но это не тема этого форума .. Но спасибо за ответ :)
C#:
void OnLootEntityEnd(BasePlayer player, BaseCombatEntity entity)
{
    Puts("OnLootEntityEnd works!");
}

OnLootEntityEnd

  • Called when the player stops looting an entity
  • No return behavior
 
  • Мне нравится
Реакции: pagan
Спасибо за ответы, завтра буду пробовать, сегодня очень устал :(( Я крутился возле этих решений но почему то пытался создать переменную а не славарь :))

Azorety Тебе отдельное спасибо, мне посоветовали посмотреть на сайте карбона, там вроде как все крючки есть и для оксида подходят, просто от души :)))

 
Вот так всё работает (на всякий если кто то ещё будет мучатся :) )

C#:
        private Dictionary<ulong, StorageContainer> PlayerBox = new Dictionary<ulong, StorageContainer>();
      
        
        [ChatCommand("nbox")]
        private void openbox(BasePlayer player)
        {
            var pos = new Vector3(player.transform.position.x, player.transform.position.y - 1, player.transform.position.z);
            string box = "assets/prefabs/deployable/woodenbox/woodbox_deployed.prefab";
            var view = GameManager.server.CreateEntity(box, pos) as StorageContainer;
            view.GetComponent<GroundWatch>().enabled = true;
            if (!view) return;
            view.limitNetworking = true;
            view.transform.position = pos;
            view.maxStackSize = 4;
            view.inventorySlots = 12;
            view.enableSaving = true;
          

            PlayerBox.Add(player.userID, view);
            view.Spawn();
            timer.In(0.1f, delegate ()
            {
                view.PlayerOpenLoot(player);
            });
            Puts("no conteyner");

        }
        [ChatCommand("opnbox")]
        private void opnbox(BasePlayer player)
        {
            if (PlayerBox.ContainsKey(player.userID))
            {
                var view = PlayerBox[player.userID];

                timer.In(0.1f, () => view.PlayerOpenLoot(player));
            }
        }
 
  • Мне нравится
Реакции: olol321
Активность
Пока никто не печатает сообщение

Похожие темы