Search the Community
Showing results for tags 'emu'.
-
Тема для размышлений. То есть тут публикуется какая-то идея, частично и полностью реализована в моих работах. Ни чего из ниже описано не будет выпущено в открытый доступ. Геобирдер на текущий момент: Работает в автоматическом режиме. Парсит только нужные меши Выборку мешей производит на основе cryEngine движка и твердых физических тел. Парсит двери и добавляет в гео Лавы, костры и другое так же добавляются в гео файл. Одна локация, один файл. Геобилдер не создает .geo файлы. Это выдуманное гавно от начальных криворуких разработчиков. Данный геобилдер создает файлы .j3o поддерживаемые jmonkey движком. В ГС полностью меняется загрузка файлов, на основе официальной поддержки .j3o файлов. Поддерживает просмотр файлов в 3d редакторе. Геобирдер доступен только для приватной разработки.
-
Тема для размышлений. То есть тут публикуется какая-то идея, частично и полностью реализована в моих работах. Ни чего из ниже описано не будет выпущено в открытый доступ. Спешу поделится замечательной новостью. Нам удалось написать ИИ, который парсит клиент, интернет и сборки серверов в поисках квестов на основе версии. В итоге мы получаем замечательный json 😃 Как видно из файла, мы получаем ID квеста, шаг, и что на этом шаге нужно сделать. В текущий момент переписываем весь квест движок, и избавляемся от хард-кодинга квестов в классах. Дата релиза и тестов скоро. (релиза не будет, частная разработка) Updated: Квестовый движок переехал в отдельный микросервис, по технологии микросерсвисов java.
-
Тема для размышлений. То есть тут публикуется какая-то идея, частично и полностью реализована в моих работах. Ни чего из ниже описано не будет выпущено в открытый доступ. Новое сетевое ядро основано на фреймворке Netty последней версии. Пример на логин сервере. Под капотом netty конечно же nio, но всю обработку он берет на себя. Код становится лаконичнее и приятнее. Обо всех преимуществах netty вы можете почитать на просторах гугла), но из особенностей можно выделить полный контроль на сетью, и дополнительные плюшки при запуске сервера на linux машинках. Пример код: public class NettyServer { private static NettyServer INSTANCE; private NettyServer() throws Exception { runServer(MainConfig.LOGIN_BIND_ADDRESS, MainConfig.LOGIN_PORT); } public static NettyServer getInstance() throws Exception { if (INSTANCE == null) { INSTANCE = new NettyServer(); } return INSTANCE; } private static final EventLoopGroup bossGroup = new NioEventLoopGroup(); private static final EventLoopGroup workerGroup = new NioEventLoopGroup(); private static ChannelFuture runServer(String ip, int port) throws Exception { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new ClientChannelHandler()); } }); ChannelFuture f = b.bind(ip, port).sync(); return f; } } Все обработки происходят в классе ClientChannelHandler, и всё. То есть читаете пакет и по op коду уже отправляете в нужное русло. Никаких вспомогательных классов, такие как Dispatcher и т.д. не нужно. То есть вот это всё уже просто удаляется, не считая того, что в самом Логин сервере. Тесты производительности будут позже, как только откроется сервер на основе этого ядра. Но пока можно ощутить стабильность пинга при большой сетевой активности. Пример когда вокруг много мобов, и тебя бьют порядка 10 мобов. В этот момент происходит огромный спам пактов SM_MOVE, SM_ATACK, SM_SPELL и так далее. Пример когда вокруг нет никого, и сетевые пакеты почти не активны.
-
… или почему комьюнити фришек всегда жалуется и будет жаловаться на дроп. Итак, если вы заглянули в эту статью, то я думаю вы представляете себе, что такое фришка Aion, эмулятор сервера и так далее. Так вот, однажды когда мне попался исходный код фришек, я сначала не поверил своим глазам, но перепроверив все открытые исходники, убедился, что так оно и есть, и это кошмар. Как рассчитывается дроп в оригинальном Aion? У моба/НПЦ, которого игрок пытается убить, есть много гипотетических ящиков с дропом. 1 ящик, это основной дроп для типа моба, там лежат предметы, которые так или иначе выпадут в дроплист с определённым шансом. 2-N – ящиков с различными наборами предметов, с которого может выпасть один, и только один предмет. У каждого предмета есть свой шанс на выпадение. Однако формула расчета тут везде разная. Для основного дропа, каждый предмет рассчитывается отдельно. Если выражаться условно то в этот ящик закидываются столько удочек, сколько предметов в ящике. Если 4 предмета, то 4 удочки, и тянеееем. Зацепилось что-то вытащили. Таким образом из основного дроп ящика, можно вытащить практически каждый предмет. Для дополнительных ящиков, работает немного другая система. Берется ящик со всеми в ней предметами, допустим ящик с синими шмотками, перемешивается, после чего туда закидывается удочка, и тянется, если что-то зацепилось, оно выпадет игроку, если нет, то уж извините. Но для каждого доп ящика, удочка кидается одна, и один раз. Шанс вытащить предмет из доп.дропа = сумме шансов для каждого отдельного предмета в ящике. Это значит, что если в ящике 10 предметов с шансом 10, то обязательно выпадет предмет. Теперь как это работает на фришках. В принципе, это работает почти так же как в оригинале. за исключением того, что: в ящиках лежит всякое гавно. да да да. Там такой хлам лежит дикий, что просто можно мозг сломать. для доп.дропа, система на фришках работает иначе. Из ящика берется случайный предмет, кладется в пустую большую коробку, и закидывается удочка. Допустим – из ящика с синим шмотом, берется случайный предмет, кладется в другой – пустой – ящик, и туда закидывается удочка. Если ничего не зацепилось, то синего шмота не видать. В общем так, для каждого ящика. Размер пустого ящика зависит от процента на предмете. Если процент 10, то ящик в 10 раз больше, если процент 1, то ящик в 100 раз больше. Разберем код: 1) class NpcDrop Цикл по каждой группе (ящик предметов) дропа в мобе. for (DropGroup dg : this.dropGroup) { if (dg.getRace() == Race.PC_ALL || dg.getRace() == race) index = dg.dropCalculator(result, index, dropModifier, race, groupMembers); } 2) class DropGroup Берем случайный предмет из группы if (this.useCategory.booleanValue()) { Drop d = this.drop.get(Rnd.get(0, this.drop.size() - 1)); return d.dropCalculator(result, index, dropModifier, race, groupMembers); } 3) class Drop По шансу этого предмета, определяем, выдает он или нет. if (Rnd.get() * 100.0F < percent) Надеюсь мне удалось объяснить вам как это действует. Попробую показать на картинке, где шанс выбить шмотку будет виден нагляднее. А почему, спросите вы? Потому-что человек, который писал первую версию фришного сервера, был далекий от игровой механики, и до ума не довел. А те кто открывают сервера по сей день, покупают “корявые” сборки у “криворуких” разработчиков. Вот так вот. Нынешние разработчики не могут сделать систему взвешенного выбора) - random weighted selection Пример кода для java public class RandomizeDrop { private List<RandomizeEntry> entries = new ArrayList<>(); private double accumulatedChance; private Random rand = new Random(); // Собираем суммированную шкалу public void addEntry(int object, float chance) { accumulatedChance += chance; RandomizeEntry ent = new RandomizeEntry(); ent.object = object; ent.accumulatedWeight = accumulatedChance; entries.add(ent); } // По шкале, селектим нужный предмет public int getRandom() { double r = rand.nextDouble() * accumulatedChance; int returnedObj = entries.get(0).object; for (RandomizeEntry entry : entries) { if (r >= entry.accumulatedWeight) { returnedObj = entry.object; } } return returnedObj; } } Спасибо за внимание!)