Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

Помогите С изменением скорости игрока

Изменить скорость можно пакетом Packet202Abilities.
Java:
//Где-то в классе//
String PackageName = "net.minecraft.server.1_6_R4";
Class Packet202Abilities = Class.forName(PackageName.concat(".Packet202Abilities"));
Class PlayerAbilities = Class.forName(PackageName.concat(".PlayerAbilities"));
Method player_minecraft = Class.forName("org.bukkit.craftbukkit.1_6_R4.entity.CraftPlayer")).getMethod("getHandle", new Class[]{});
//Где-то в классе//
Object constructPacket202(Player p, float walk, float fly)
{
    Object packet = Packet202Abilities.getConstructor(new Class[]{PlayerAbilities}).newInstance(playerAbilities(p));
    fieldSet(packet, "e", (float) fly);//def 0.5
    fieldSet(packet, "f", (float) walk);//def 0.1
    return packet;
}
void fieldSet(Object o, String name, Object value)
{
    Field field = o.getClass().getDeclaredField(name);
    field.setAccessible(true);
    field.set(o, value);
}
void sendPacket(Player p, Object packet)
{
    Object playerConnection = player_minecraft.getReturnType().getField("playerConnection").get(player_minecraft.invoke(p));
    Method sendPacket = playerConnection.getClass().getDeclaredMethod("sendPacket", new Class[]{Packet});
    sendPacket.setAccessible(true);
    sendPacket.invoke(playerConnection, packet);
}
//Где-то в классе//
@EventHandler
void onPlayerJoin(PlayerJoinEvent e)
{
    sendPacket(e.getPlayer(), constructPacket202(e.getPlayer(), 0.01F, 0.05F));
}


Этот же пакет игроку шлётся при setWalkSpeed. Т.е. как я понимаю, результат будет такой же.
 
Этот же пакет игроку шлётся при setWalkSpeed. Т.е. как я понимаю, результат будет такой же.
Более явная отправка пакета, работа в более ранних версиях, где нет setWalkSpeed, к тому же я не это хотел написать (:
Я хотел написать изменение NBT тега abilities:walkSpeed. Эффект от изменения такой же, но сохраняется при перезаходе, да отсутствует необходимость постоянно отправлять какие-то специфичные пакеты.
 
Ission, а вот это гораздо интереснее. Вообще странно, что в API не добавили доступа к этим тегами.
 
Ission, а вот это гораздо интереснее. Вообще странно, что в API не добавили доступа к этим тегами.
Это печально. Они вообще против того, чтобы кто-либо пользовался NBT через плагины. Именно когда количество кодеров пользующихся NBT начало увеличиваться они начали использовать в названии пакетов версию. Но при всём при этом они с 1.2 не могут добавить API для редактирования многих функций спавнеров, которые появились с 1.2, а так же были добавлены новые, но позже. Нет API для падающих блоков, которое позволяет нормально ронять те же сундуки без пропадения всего, что в них. У них нет API для вагонеток с блоками, а API для вагонеток со спавнерами поражает своим многообразием функций. И таких примеров ещё много. Но с другой стороны например моб с тегом SHORT вместо BYTE крашит клиент при попадании в зону видимости этого моба, так же этот моб становится неудаляемым при помощи Entity.remove(); и может положить карту.
 
Нашел этот плагин. Тут тоже все на евентах сделано. Сейчас попробую тоже на евентах сделать.
В моём плагине изменения скорости всё построено на setWalkSpeed(). Может быть это особенности версии, так как я пишу на 1.5.2.
 
Прошу оценить мой костыль:
Код:
@SuppressWarnings("deprecation")
    @EventHandler
    public void onMove(PlayerMoveEvent event){
        //event.getPlayer().sendMessage("В МУВЕ евенте: " + event.getPlayer().getWalkSpeed());
      
        if(event.getPlayer().getActivePotionEffects().isEmpty()){
            double x = 0;
          
            if(event.getPlayer().getInventory().getBoots() != null){
                switch (event.getPlayer().getInventory().getBoots().getTypeId()) {
                case 305:
                    x+=0.25;
                    break;
                case 317:
                    x+=0.25;
                    break;
                case 309:
                    x+=0.5;
                    break;
                case 313:
                    x+=0.75;
                    break;
                }
              
            }
          
            if(event.getPlayer().getInventory().getLeggings() != null){      
                switch (event.getPlayer().getInventory().getLeggings().getTypeId()) {
                case 304:
                    x+=0.5;
                    break;
                case 316:
                    x+=0.5;
                    break;
                case 308:
                    x+=0.75;
                    break;
                case 312:
                    x+=1.0;
                    break;
                }
              
            }
          
            if(event.getPlayer().getInventory().getChestplate() != null){
                switch (event.getPlayer().getInventory().getChestplate().getTypeId()) {
                case 303:
                    x+=0.5;
                    break;
                case 315:
                    x+=0.5;
                    break;
                case 307:
                    x+=0.75;
                    break;
                case 311:
                    x+=1.0;
                    break;
                }
              
            }
          
            if(event.getPlayer().getInventory().getHelmet() != null){
                switch (event.getPlayer().getInventory().getHelmet().getTypeId()) {
                case 325:
                    x+=0.25;
                    break;
                case 314:
                    x+=0.25;
                    break;
                case 306:
                    x+=0.5;
                    break;
                case 310:
                    x+=0.75;
                    break;
                default:
                    break;
                }
            }
            if(x >= 1.5 && x < 3.5 ){
                event.getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 200, 0));
                event.getPlayer().sendMessage("1");
            }else if (x == 3.5){
                event.getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 200, 1));
                event.getPlayer().sendMessage("2");
            }else{
                return;
            }
      
        }
      
      
    }
Минусы:
- Эффект снимается не сразу после исчезания брони.
- Не гибкая настройка (всего 3 режима)
- Видимо сильно нагружает сервер, когда коэффициент тяжести < 1.5

Den_Abr, если делать шедулером, то когда его запускать? Например, сделать его в onEnable и каждые 30 секунд проверять всех игроков на сервере, но тогда, мне кажется, будут те же проблемы, что и тем, что сделал я.

Ission, какие еще есть способы изменения скорости игрока?
Den_Abr, протестировал я ваш плагин. Действительно - изменение скорости не работает :( Рывок, а потом снова обычная.
Изменения высоты прыжка, кстати, тоже - что бы не писал, всегда в чат пишет одно и то же:
5r6Zc.png
 
Прошу оценить мой костыль:
Den_Abr, если делать шедулером, то когда его запускать? Например, сделать его в onEnable и каждые 30 секунд проверять всех игроков на сервере, но тогда, мне кажется, будут те же проблемы, что и тем, что сделал я.

Ission, какие еще есть способы изменения скорости игрока?
Я хочу, чтобы при ношении брони скорость снижалась. Должен быть евент надевания брони.
Тут тогда проблема - что если игрок вышел и зашел, броню он не одевает, а скорость нужно снизить.
2 варианта, которые будут уместны:
1. Создать выделенный поток и 2 HashMap'а. Один-хешкарта занимается хранением ника и последней копией инвентаря. Вторая хешкарта занимается хранением ника и модификатора скорости. Поток анализирует данные из Один-хешкарты и после анализа их удаляет(чтобы анализоровать только при изменении), а во вторую хешкарту записывает уже после анализа.
2. Это 1.6+? Достаточно изменить крафт доспехов и установить на каждый доспех модификатор скорости в процентах, с 1.6 это стало доступно. Единственная проблема, что как всегда bukkit'овцы и не чешутся в добавлении возможности различных модификаторов, доступные через редактор карт или NBTeditor'ы какие-нибудь например. По этому тут тоже придётся попотеть, но это идеальный вариант. Вся работа плагина сводится к смене результатов крафта при запуске. Никаких слушателей, потоков, проверок инвентаря...
 
Ission, можете кинуть пример, пример плагина, или что почитать? Никогда с этим не работал.
 
Ission, можете кинуть пример, пример плагина, или что почитать? Никогда с этим не работал.
Java:
//Где-то в коде Один раз//
plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin,
                new SpeedMod(SClassInstance), 100, 100);
//Где-то в коде Один раз//
//Где-то в коде Один раз//
plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin,
                new playerAnalizator(SClassInstance), 100, 100);
//Где-то в коде Один раз//
//Когда мы решили просмотреть инвентарь игрока//
SClassInstance.playerMod.put(Player.getName(), Player.getArmorContents());
//Когда мы решили просмотреть инвентарь игрока//
public class SClass
{
    private final HashMap<String, ItemStack[]> playerMod = new HashMap<String, ItemStack[]>();
    public final HashMap<String, Integer> speedMod = new HashMap<String, Integer>();
    public static class SpeedMod implements Runnable
    {
        private final SClass sc;
        public SpeedMod(SClass sc)
        {
            this.sc = sc;
        }
        @Override
        public void run()
        {
            synchronized(sc.speedMod)
            {
                //перебираем speedMod и модифицируем скорость всем игрокам на основе показателей
            }
        }
    }
    public class playerAnalizator implements Runnable
    {
        private final SClass sc;
        public playerAnalizator(SClass sc)
        {
            this.sc = sc;
        }

        @Override
        public void run()
        {
            HashMap<String, Integer> speedMod = new HashMap<String, Integer>();
            HashMap<String, ItemStack[]> playerMod = new HashMap<String, ItemStack[]>();
            synchronized(sc.speedMod)
            {
                playerMod.putAll(sc.playerMod);
                sc.playerMod.clear();
            }
            //Перебираем playerMod на наличие брони и заносим в список speedMod
            putAll(speedMod);
        }
        private void putAll(HashMap<String, int value)
        {
            synchronized(sc.speedMod)
            {
                sc.speedMod.putAll(speedMod);
            }
        }
    }
}
Вот пример кода по первому пункту, как Один из вариантов решения данной проблемы. Код не полный, без анализа, но думаюВы разберётесь. По второму пунтку так как у Вас MCPC+ я никаких советов дать не могу.
 
Ission, спасибо, буду разбираться.
 

Поделиться этой страницей

Назад
Верх