no bps rust что это
Чего не стоит делать в Rust, если начали играть в 2021 году
Rust – это необычный симулятор выживания, который привлек к себе внимание огромное количество геймеров. При этом новички часто думают, что в этом проекте нет ничего сложного, и уже с самого начала делают все то, что и в других играх с элементами выживания.
К сожалению, Rust не отличается особым гостеприимством по отношению к новым игрокам, поэтому стартовать бывает довольно сложно. Перед вами подборка главных ошибок, которые делают новички, решившие поиграть в Rust в 2021 году.
Одному будет тяжело
Rust – далеко не самая лучшая многопользовательская игра для одного человека. Здесь есть несколько этапов развития, и добраться до каждого из них можно только за счет продолжительного гринда. Если играть в команде со своими друзьями, то вы гораздо быстрее достигните цели, чем в одиночку.
Также стоит отметить, что 99% других игроков не дадут вам мирно существовать в виртуальном мире игры. Вам постоянно придется отбиваться от обезумивших «дикарей», которые захотят отобрать ваши вещи и ресурсы. Естественно, ни у одного новичка не получится защитить себя от оравы более опытных игроков, поэтому лучше изначально залетать в Rust хотя бы с парой друзей.
Никому нельзя верить
Этот пункт частично противоречит предыдущему, но при этом он еще более важен. Прежде всего вам стоит забыть о том, что взаимодействие с другими игроками в многопользовательских проектах – это норма. Rust вообще не та игра, где нужно объединяться с незнакомыми людьми, чтобы вместе получить больше лута или ресурсов. Здесь вы можете рассчитывать только на себя, и если начнете доверять первому встречному игроку, то очень скоро поймете, почему этого нельзя делать. Особенно это касается товарищей с хорошей экипировкой, которых вы встретите на своем пути.
Дело в том, что в Rust каждый играет сам за себя, а опытные игроки очень часто обманывают новичков самыми разными способами. Незнакомец, который предложит побегать с ним по виртуальному миру и при этом будет носить броню заметно лучше вашей, скорей всего грифер. Это такой игрок, который при первой же удобной возможности просто вас убьет и заберет все вещи. Так что, начиная играть в Rust, никому не доверяйте!
Курс юного строителя
Если вы вдруг не знали, то в Rust есть строительство, и здесь оно играет довольно важную роль. При этом данная механика имеет ряд особенностей, которые придется изучить в самом начале знакомства с игрой, иначе ваши архитектурные «шедевры» будут попросту разваливаться, а вы впустую потратите ценные ресурсы.
Прежде всего стоит отметить, что у каждого строительного блока есть мягкая и твердая сторона. Во время строительства блок всегда нужно устанавливать таким образом, чтобы твердая сторона находилась снаружи будущего здания. Если не соблюдать это правило и размещать материалы как попало, то вашу постройку сможет развалить первый попавшийся игрок, причем с помощью обычного топора или кирки. Согласитесь, будет не очень приятно наблюдать за тем, как несколько часов ваших трудов кто-то разбирает по кирпичикам за считаные минуты.
Все вещи в одном месте
Огромное количество игроков в Rust вообще не уделяют время крафту. Они считают, что гораздо проще украсть готовые предметы у других пользователей, чем стоять у станка и пытаться что-то сделать. Именно поэтому в этой игре противопоказано хранить все свои вещи в одном месте.
Ни в коем случае не размещайте абсолютно все запасы на единственной базе, да еще и в конкретном помещении. В таком случае после случайного налета кучки любителей халявы вы потеряете абсолютно все. Конечно, вряд ли у новичка хватит ресурсов, чтобы построить себе 4-5 домов и правильно распределить по ним ценные предметы, но хотя бы попробуйте сделать что-то подобное. Неплохим решением будет на территории одной базы построить несколько «нычек» и распределить по ним ресурсы и предметы.
Не забывайте про аптечки
Если вы решите, что аптечки вам не нужны и со своим крутым автоматом вы сможете одолеть кого угодно, то Rust очень быстро вас разочарует. Здесь очень просто погибнуть, и иногда вы даже не будете понимать, почему это вообще произошло. В результате игрок, у которого было полно аптечек, просто завалит вас рандомной палкой и заберет тот самый крутой автомат.
Поставьте себе домофон
Если же вы не можете сделать кодовый замок или уже поставили везде обычные двери, то не делайте ключ. Пускай доступ к зданию будет только у вас. Отсутствие ключа гарантировано защитит ваши владения, даже если вы внезапно погибнете.
Не используйте факел
Дело в том, что свет от факела моментально привлечет к вам внимание других игроков. Часть из них будет гриферами, которые быстро прибегут на ваш «сигнал» и просто убьют. На этом ваш многообещающий забег в Rust просто закончится и придется начинать все сначала. Первое время лучше бегайте без факела и пытайтесь ориентироваться на карте с помощью своего зрения.
Вы всегда в опасности
Многие новички ошибочно думают, что после того, как они построят себе укрытие и обзаведутся хоть какой-то экипировкой, можно просто расслабиться и наслаждаться игровым процессом Rust. Этот проект не об этом, вы всегда будете под прицелом у других игроков! Причем если у вас вдруг все слишком хорошо и на это обратят внимание остальные пользователи игровой сессии, то очень скоро вас ждет набег незваных гостей.
Перестрелка – не самая лучшая идея
Некоторые новички в Rust почему-то считают, что это экшен-шутер, в котором прямо-таки необходимо ввязываться в перестрелки и каждую минуту показывать, кто здесь круче. На самом деле проект про выживание, и я вам гарантирую, что ваша беготня с автоматом закончится очень быстро, если вы вдруг решите, что можете держать всю карту в страхе.
Вот такие советы мы решили дать новичкам, которые только надумали залететь в Rust! Делая все эти вещи, вы гарантировано проживете в виртуальном мире игры чуточку дольше и при этом гораздо лучше узнаете все тонкости проекта. Главное, не забывайте всегда быть начеку, здесь нет зоны комфорта.
Конспектируем Книгу Rust:: Владение
Перед вами краткое профессиональное описание особенностей языка Rust для профессионалов.
Чего здесь НЕ будет
Содержание
Мотивация
Моя история изучения языка Rust началась со статьи Как мы ржавели. История внедрения и обучения. В ней Nurked предложил оригинальный способ прочтения Книги — читать главы надо не по порядку, а в последовательности [4, 3, 5, 6, 8, 4, 9, 7, 10, 4, 13, 17, 15, 16]. Со многими тезисами этой статьи я склонен в той или иной степени согласиться, в частности, с тем, что «первая глава этого руководства должна гореть в печи». Конечно же, вместе со второй, в которой разбирается вот этот пример:
Именно на этом примере я в свое время закрыл Книгу — неинтересно. К тому же, за println!(. ) явно скрывается некий макроязык, а к ним у меня стойкая аллергия со времен работы с Microsoft Foundation Class. Ну, в общем — нет, спасибо, не надо.
После повторной подачи от Nurked начал с главы 4 и появился интерес. Как пишут сами авторы Книги:
Владение является наиболее уникальной особенностью языка Rust. Благодаря ей в Rust осуществляется безопасная работа с памятью без необходимости использования автоматической системы сборки мусора (garbage collector).
С этого и надо было начинать. Я отношусь к той категории людей, которые несколько измучены нарзаном недовольны нюансами работы с GC в рамках highload, засим текст нашел внимательного читателя в моем лице. В процессе чтения главы 4 я обнаружил, что Книга рассчитана на совсем новичков и переполнена скучными подробностями, поэтому изначально у меня была идея просто законспектировать суть, отсекая все лишнее. Но эта идея потерпела крах, так как оказалось, что для понимания принципов работы с памятью после главы 4 надо читать главу 10.3, потом главу 15, при этом текста много, он содержит ошибки и его совершенно недостаточно. Для понимания пришлось дополнительно читать, например, это, это, это, это и вот это, но нужных мне примеров я так и не нашел.
Мне представляется, что достаточно глубокое описание особенностей языка Rust может быть дано в рамках короткой серии относительно небольших статей, без отсыла читателя к другим источникам. В процессе написания такого материала, конечно, сам получаешь хорошие знания, так что, надеюсь, затея будет выгодна как автору, так и читателям.
На кого рассчитан материал
Читатель должен владеть на уровне middle+ двумя языками программирования (один с GC, один без него), они послужат донорами абстракций, которые в тексте не поясняются.
Из тех языков, с которыми я плотно работал, Rust ближе всего, КМК, к Go. Их роднит отсутствие «нормального ООП», отсутствие «нормальных исключений», концепция срезов (slice), наличие как объектов, так и ссылок/указателей на них, возможность возвращать несколько значений из функций, страшное слово unsafe, ну и, конечно, кросс-компиляция «из коробки». В Go пока нет обобщенных типов, но про них знают и их ждут, поэтому опытного гофера ржавчиной не испугать.
Что делать, если знаешь только один язык? План Б.
Особенности изложения
Изложение в первую очередь сфокусировано на той самой безопасной работе с памятью, которая и является основной «фишкой» Rust. Остальное часто дается «мимоходом» и подчинено главной цели.
Скачивать и ставить ничего не нужно, с примерами можно работать через play.rust-lang.org.
Финализация через drop()
Когда объект покидает область видимости (variable scope), его «финализируют» через вызов метода drop(). В этом деструкторе можно произвести некие завершающие действия — возвратить память в кучу, закрыть соединение и т.д. Для примера создадим экземпляр типа String с помощью конструктора фабрики String::from() :
String хранит свои данные в куче, и компилятор Rust любезно обеспечит неявный вызов s.drop() после закрывающей скобки, тем самым давая возможность вернуть использованную память.
«Книга» утверждает, что управление памятью осуществляется через «владение» с набором правил, которые компилятор проверяет во время компиляции программы. Полезно сразу иметь в виду (напомню — материал для опытных камикадзе), что есть некие:
Иными словами, если память выделяется в куче, а полученные объекты ссылаются друг на друга — будь готов к граблям, засадам и к поиску утечек памяти.
Изменяемость переменных
Я думаю, Rust имеет потенциал находить отклик в сердцах многих. let как в Бейсике, <> как в Java, :: как в С++, объявление функции похоже на таковое из Go (только там func )
Владение (Ownership) и его передача присваиванием (Move)
Ключевое правило: Каждое значение имеет одного и только одного владельца-переменную
После операции присваивания переменная типа String перестает владеть своим бывшим значением, и ее нельзя больше использовать:
Для простых типов (primitive types), однако, значение копируется, а не передается, и для них многократное присваивание выглядит обычным образом:
Передача и возврат параметра по значению
При передаче переменной в функцию по значению происходит и передача владения (если тип не реализует интерфейс trait Copy ):
Ссылки и заимствование (References and Borrowing)
Необязательно брать значение во владение, его можно «занять» (borrow):
От перестановки строк из примера выше результат меняется, можно раскомментировать строки и все будет работать:
Висячие ссылки (Dangling References)
Компилятор Rust гарантирует, что эта проблема искоренена полностью. Рассмотрим такой пример:
Здесь мы заводим локальную переменную и затем возвращаем ссылку на нее. Что, конечно, очень плохо, так как переменной и ее значения после возврата из функции больше нет, а ссылка на несуществующее — есть.
Компилятор откажется работать в таких условиях, в качестве причины отказа он приведет загадочную формулировку: «error[E0106]: missing lifetime specifier». Загадка lifetime specifier получит раскрытие в следующих главах.
В свое время был удивлен, что в Go таки можно вернуть указатель на локальную переменную, и за это тебе ничего не будет:
На деле хитрый компилятор в этом случае выделяет память в куче:
Срезы (Slices)
Но то строки, с байтами ситуация попроще:
Теперь, собственно, про владение. Взятие среза «одалживает» всю последовательность на чтение, менять ее теперь нельзя:
Явное указание типов для slice не всегда очевидно:
[EU] iRaid 5X No BPs
Информация
Сервер [EU] iRaid 5X No BPs
Игровой сервер Rust[EU] iRaid 5X No BPs всегда рад новым игрокам. Начните играть у нас прямо сейчас! Что же можно сказать о сервере? Это сервер онлайн игры Rust версии 2223, который работает на карте Procedural Map. С особенностями и требованиями игры можно ознакомиться в обзоре Rust. Cейчас сервер недоступен и заполнен на 0%.
Игровой сервер [EU] iRaid 5X No BPs доступен по адресу 173.199.75.28:28016 и его uptime составляет %. Это означает, что он работает не очень стабильно в последнее время. Так же сервер участвует в рейтинге игровых серверов и занимает там 1925 позицию. Ранее сервер был на 2301 позиции, а при последнем расчете сервер поднялся в рейтинге.
Игроков за сутки
Игроков за месяц
В интернете огромное множество серверов различных игр, но не все игровые сервера имеют свой сайт или страницу с информацией. Это затрудняет вход на сервер и игроки могут его просто пропустить. Наш проект дает возможность предоставить игрокам исчерпывающую информацию о Вашем сервере и упростить его администрирование.
На проекте уже представлены различные Rust сервера, в том числе [EU] iRaid 5X No BPs сервер. Это представитель игровых серверов, на которых вам будет приятно играть одному или же с друзьями. Играть в Rust можно по разному и лучше делать это хорошо. Играйте у нас, играйте вместе с нами!
Чем Rust отличается от «плюсов»: откровение ветерана С++
Rust часто называют преемником C++. Дмитрий Свиридкин рассказал на суровом программистском языке, так ли хорош любимчик пользователей Stack Overflow.
Polina Vari для Skillbox Media
Программист. Разрабатывает на C++ и Rust решения для платформы компьютерного зрения в Arrival. Автор сборника материалов по C++.
Я решил попробовать Rust, потому что устал отлавливать на код-ревью (и не только) одни и те же ошибки в «плюсах». Обязательно кто-нибудь объявит статик-лямбду и захватит в неё по ссылке нестатический временный объект. А когда код с такими ошибками коммитят, он проходит тесты, предполагающие однократный запуск. Программа попадает в продакшен, где запускается пару раз и падает. На поиск и отладку багов уходит много сил и времени.
В Rust нет бардака с библиотеками
У С++ всегда было две проблемы: недостаточная квалификация разработчиков и отсутствие нормальных пакетных менеджеров.
Раньше приходилось гуглить, копировать и компилировать исходники библиотек — та ещё головная боль. Бывало, найдёшь исходники, а компилятор не подходит, потому что он слишком старый, хедеры протухшие или версии зависимостей не совпадают. Тогда вместо готового решения придумывали своё — и это своё всегда заканчивалось кучей багов.
Например, я видел реализации std::optional, которые не вызывают деструктор, даже если тип нетривиально деструктурируемый. Тогда как стандартная реализация — это куча boilerplate-кода, который даже командой из трёх-четырёх человек невозможно отладить.
Получается полный бардак. Часть кода покрывают тестами, она кое-как работает, а когда начинаешь детально тестировать — тут дедлок, там use-after-free и так далее. В Rust эти заботы можно частично переложить на плечи компилятора, но с ним иногда приходится бороться: богатая система типов требует более педантичной работы.
Чтобы писать на Rust, мне не пришлось менять IDE. Просто подключил к VS Code code-assistant rust-analyzer (это что-то вроде майкрософтовского IntelliSense). На прошлой работе писали в CLion от JetBrains. У неё есть неплохой плагин для Rust, но при рефакторинге он может наделать делов и оказать медвежью услугу. Так что IDE от JetBrains научили меня не доверять авторефакторингу — обязательно что-нибудь да сломается. Поэтому стараюсь аккуратно рефакторить сам.
Система типов в Rust защищает от ошибок
Бизнес-логика — именно то, что нужно писать на Rust, потому что с ним тяжело ошибиться. Ещё на прошлой работе мы запилили плагин — в качестве proof of concept того, что на Rust вообще можно создавать плагины к большому SDK. Логика была примитивная: принять список слов и проверить, совпадает ли с ним input.
Почему такой простой плагин? Потому что больше никто в команде не знал Rust. Язык молодой, и пока на нём мало кто пишет. Создавать проекты, которые может поддерживать только один разработчик, невыгодно. Проще найти «плюсовиков», поэтому C++ никуда не исчезнет.
На новой работе я перевожу часть проекта с «плюсов» на Rust. Язык подкупил меня мощной системой типов, которая позволяет выразить зависимости между временами жизни объектов. В языках с ещё более мощными системами типов, например с зависимыми типами, можно проверять статически рантаймовые ограничения. Например, запретить функции принимать пустые строки — компилятор проверит.
Однако у таких мощных языков есть общая проблема: вы замучаетесь доказывать компилятору, что код работает правильно и ничего в нём не нужно исправлять. К счастью, Rust не совсем такой, это золотая середина: с одной стороны, его система типов достаточно строгая, чтобы защитить вас от распространённых ошибок. С другой — не настолько строгая, чтобы приходилось мучиться с ней лишнего.
Программы на Rust без стороннего кода сравнимы по скорости с «плюсовыми»
На прошлой работе я переписывал большой графовый алгоритм — без unsafe-кода, с контейнерами из стандартной библиотеки.
По производительности программа была всего на 10% медленнее «плюсовой». При этом обошлись без стороннего кода. Считаю, что результат хороший. Под C++ пришлось три месяца искать hashmap и перебирать варианты: в одной выравнивание как-то хитро сконфигурировано и приводит к segfault, в другом exception вылетает, если хеш плохой, третий вообще уже четыре года не поддерживается.
Что же касается бенчмарков, то всегда можно подобрать тест, где выиграет нужный язык — хоть С++, хоть Rust. Достаточно знать тонкости работы с памятью в конкретном языке. Я, например, могу написать пример кода на Rust без лишних аллокаций, а в «плюсах» у аналогичной программы они будут, потому что организовать там safe по-другому нельзя. В общем, обсуждать производительность нужно на конкретном примере.
Code-assistant rust-analyzer отлично работает с шаблонами
В последнее время я оборачиваю небезопасные библиотеки языка С, чтобы подцепиться к каноническому Rust API. Если бы сразу начал писать на «плюсах», уже давно бы закончил и общался с железом, к которому эта библиотека поставляется. А так как пишу на Rust, то пришлось целую неделю аккуратно оборачивать код в канонические Rust-структуры. Столкнулся с тонкостями системы типов: вариантностью ссылок, контравариантностью типов. Если не обращать на них внимания, то safe-обёртка над C API будет некорректной.
Оборачивать низкоуровневый unsafe-код в safe на Rust довольно долго, но оно того стоит. «Плюсовой» IntelliSense вряд ли сравнится с мощным rust-analyzer и справится далеко не со всем кодом, особенно с шаблонами.
Возможно, с появлением стандарта С++20 появятся хинты и IntelliSense научится подсказывать внутри шаблонного кода, если в параметрах указать концепт. Думаю, раньше всех эту фичу внедрит в свои IDE JetBrains — если уже не начала втихаря над ней работать. Шаблоны без концептов в «плюсах» всегда работали плохо: стоит поставить неподходящий аргумент — и компилятор выдаёт огромные сообщения об ошибках. Пока у анализаторов Rust гораздо больше возможностей, да и писать шаблонный однотипный код на нём получается гораздо быстрее.
У Rust настоящая zero-cost abstraction
Помимо Rust, я присматривался и к другим языкам. Три года назад, когда впервые сменил работу, думал погрузиться в светлый мир JVM и написать что-нибудь на Kotlin. Но языки вроде Scala, Java и Kotlin можно применять далеко не везде. Виртуальные машины создают дополнительную нагрузку и для встраиваемого ПО в микрокомпьютерах не подходят. В таких системах пишут на чистом С, С++ или совсем страшных штуках вроде MISRA C.
У Rust, скомпилированного в native, нет дополнительного рантайма. RAII, деструкторы, конструкторы как в «плюсах». Только у Rust линейные типы и zero-cost с ними настоящий, а у C++ — нетривиальный деструктор у типа, и хоть убейтесь, но не получится передать его значение через регистры.
Ещё есть Zig — он очень похож на Rust. Там, например, тоже есть проверка lifetime, но организована она иначе, и то, как это сделано в Rust, мне нравится больше. Других языков с проверкой lifetime я не знаю, а в языках со сборщиками мусора она не нужна: если есть ссылка на объект, значит, он точно живой.
В Go механизм похожий, но там есть сборщик мусора. Мне предлагали перейти на него четыре года назад. Я попробовал, и синтаксис меня рассмешил. Стоит автоформатеру неправильно перенести строки, и программа не скомпилируется. А всё из-за неявной расстановки точек с запятой.
С похожей проблемой я сталкивался, когда мы в первый раз подключали сторонний форматер для «плюсов» — кажется, это был Uncrustify. Он убрал лишние фигурные скобки, и размер критических секций у меня резко вырос. Да уж, отличный форматер — поменял поведение программы. Мог бы просто весь код снести.
В Rust более лаконичный синтаксис, но к нему нужно привыкнуть
Вообще, синтаксис Rust меня вначале сильно раздражал, но я уже почти смирился с ним.
Раздражает символ ; в конце expression, который меняет возвращаемый тип на аналог сишного void. Поставил точку с запятой — программа перестаёт компилироваться. А компилятор молотит type-чекером, который занимает целое ядро, чтобы rust-analyzer и IDE написали красным: «Смотри, у тебя тут типы не сошлись».
Хорошо хоть в экосистеме Rust пофиксили много ошибок и в поставке уже есть официальный форматер, который всё делает правильно. Конечно, тоже есть проблемы. Например, если вы хотите сделать что-то серьёзное с пакетными менеджерами, например сложить собранные артефакты в каталог, то придётся вручную писать поверх скрипты, например на Bash. Штатными средствами это сделать либо нельзя, либо они unstable.
В целом я свыкся с упоротым синтаксисом и краткими ключевыми словами, но всё равно считаю, что они должны состоять хотя бы из трёх символов. Я люблю называть свои переменные fn, а мне его предлагают в качестве ключевого слова. С другой стороны, минималистичный синтаксис — это хорошо.
Лямбды можно писать кратко и без ключевого слова return — это экономит кучу времени. Зато когда после этого переключаешься на С++, то всё время забываешь писать return и, указав тип возврата, получаешь функции с неопределённым поведением. В С++ синтаксис лямбд вообще напоминает синтаксис обычных функций, только trailing return type сделали — ну, и на том спасибо, что уж там. А скобки и return нужно писать обязательно, иначе будете ждать от функции int, а она ничего не вернёт.
При этом Rust не панацея
Тех, кто только планирует погрузиться в Rust, предупреждаю: это не панацея от всех болячек C++. Он защищает вас от гонки данных через проверку borrow checker, но пропускает дедлоки. Защищает от use-after-free, но только в safe-подмножестве. Если же работаете с unsafe — у вас, по сути, будет тот же С++, только с более продвинутой стандартной библиотекой.
Хотя и здесь не всё так однозначно. Многие важные фичи, например для разработки драйверов или встроенного ПО, остаются нестабильными, а значит, писать на Rust серьёзные проекты пока рискованно. По этой причине от Rust часто отказываются в пользу C++, где всё давно stable и unsafe.