Защита от спама пакетов нанесения урона

Версия Minecraft
1.7.10
1,196
31
183
Так, собсна, возникла трабла, вопрос скорее к Агру, но мб кто то тоже это решил
Короче, юзаю расчеты выстрела (разброс, вся дичь) на клиенте, чтобы меньше ощущалась задержка в виде пинга, если бы я спавнил энтити пулю.
Далее, посылаю пакет с айдишником сущности, булев хедшот, и три позиции сущности
Java:
 public PacketShoot(int toSend, boolean headshot, double posX, double posY, double posZ) {
        this.toSend = toSend;
        this.headshot = headshot;
        this.posX = posX;
        this.posY = posY;
        this.posZ = posZ;
      }
На клиенте код обработки всего этого вырезан, но вот в чем проблема
Челик читер гетает этот пакет, циклом проходится по прогруженным игрокам, на каждого посылает такие пакеты, данные все берет тоже оттуда с игрока из цикла (хедшот тут не играет роли, дамаг энивей наносится), и получается, мы имеем челика который всех прогруженных игроков убивает
Проверки в пакете на пушку в руках есть, все это есть, но челик держа пушку в руках все так же сможет убивать всех
Кто нибудь знает, как такую дичь можно пофиксить, или придется переходить на энтити пулю?
 
Решение
Тебе не раз в секунду нужно это делать, а каждый тик. И у тебя должна быть не одна переменная которая меняется раз в секунду, а массив "истории", размер которого равен количеству предыдущих тиков истории.
Что-то типа такого, я не помню уже:
Java:
AxisAlignedBB[] states = new AxisAlignedBB[20]; // 20 тиков истории
int currentStateIndex;

update(){
    if(currentStateIndex >= states.length){
        currentStateIndex = 0;
    }

    states[currentStateIndex++] = player.boundingBox.copy();
}

checkHit(){
    AxisAlignedBB currentState = states[player.ping / 20];
    AxisAlignedBB box = player.boundingBox.copy();
    player.boundingBox.setBB(currentState);
    // raycast
    player.boundingBox.setBB(box);
}

tox1cozZ

aka Agravaine
8,455
598
2,892
Чтобы такого не было, нужно raycast делать на сервере. А чтобы все работало хорошо, нужно делать лаг-компенсацию, инфы по этой технике довольно много в инете.
Ибо когда клиент решает попал он или нет, серверу сложно будет проверить достоверность этой инфы.
 

tox1cozZ

aka Agravaine
8,455
598
2,892
lag compensation гугли
 
1,196
31
183
Спасибо, я нашел одну занимательную статейку на хабре, она более понятна чем то шо ты скинул, + посмотрел видос как это работает в кс го
тык
Еще вопрос, как думаешь, все так же через вектор рассчитывать на сервере уже, или юзать пулю? Просто не сильно хочется грузить сервак лишними сущностями.
И если не сложно, я вчера ночью эти статейки читал, 50/50 понял. Но что примерно нужно делать? У меня тут есть идейка, рассчитывать позиции атакуемой сущности пинг-время назад, и с этим работать. Но майн вообще хранит предыдущие позиции сущности кроме позиции в предыдущий тик аля prevPos*?
 

tox1cozZ

aka Agravaine
8,455
598
2,892
как думаешь, все так же через вектор рассчитывать на сервере уже, или юзать пулю?
Если баллистика не нужна, то raycast лучше наверное.
Но что примерно нужно делать?
Тебе нужно сохранять boundingBox всех энтитей(которые двигаются) хотя бы на 20 предыдущих тиков. Игрок стреляет, ты по пингу высчитываешь сколько тиков назад на сервере были актуальны позиция для этого игрока, сетишь всем энтитям этот AABB, делаешь raycast, детектишь попадание, откатываешь AABB энтитей обратно.
 
1,196
31
183
Так, то есть, если я тебя правильно понимаю
В IEEP хранить несколько боксов сущностей 20/40/60 тиков назад
В тикере обновлять это (думаю юзнуть PlayerTickEvent)
В рассчетах сетать AABB ВСЕХ сущностей (вроде догадываюсь почему всех, ведь сервак не знает по какому челу конкретно стреляющий палил) на AABB какой либо тиков назад, и там уже райтрейсить, так?
И да, где в майныче пинг лежит? Я раньше пытался его найти, но не нашол чото вообще. Ищу на серверной стороне, ясно дело
UPD:
Перед тем как рассчитывать (извиняюсь я с ААББ так себе в плане его изменения перемещения, грешу что неправильно сделал) делаю вот так
Java:
for (Object o : w.playerEntities) {
                            if (o instanceof EntityPlayer) {
                                EntityPlayer player = (EntityPlayer) o;
                                AxisAlignedBB prevAABB = ExtendedPlayer.get(player).prevAABB;
                                player.getBoundingBox().expand(prevAABB.maxX, prevAABB.maxY, prevAABB.maxZ);

                            }
                        }
Правильно ли?
 
Последнее редактирование:

tox1cozZ

aka Agravaine
8,455
598
2,892
Ну можешь не всех вообще сущностей в мире, а в каком-то радиусе, вряд ли выстрел будет дальше чем 512 блоков, например.
И да, где в майныче пинг лежит?
EntityPlayerMP#ping

Только проблему "убийства за стеной" это не решает.
Есть игрок1 с 200 пингом, у него на экране игрок2 рядом со стеной. Игрок1 стреляет в него, но в этот момент игрок2 уже сделал шаг за стену и у себя на экране он уже за стеной и тут его резко убивают, ибо сервер подстроился под пинг игрока1, у которого игрок2 все еще не за стеной.
 
1,196
31
183
проблему "убийства за стеной"
да это еще маленькое зло, по сравнению с диким упреждением. Я читал твою тему насчет этого, потом как нибудь решу, наверно)
выше код приложил, посмотри
 
1,196
31
183
Так, понял. В мапу занес всех игроков и их боксы (потом накину оптимизацию)
Сетаю всем аабб, произвожу рейтрейс, после всего снова прохожусь по мапе и возвращаю боксы.
Код (это в начале перед рейтрейсом):
Java:
HashMap<EntityPlayer, AxisAlignedBB> boxes = new HashMap<>();
                        for (Object o : w.playerEntities) {
                            if (o instanceof EntityPlayer) {
                                EntityPlayer player = (EntityPlayer) o;
                                boxes.put(player, player.boundingBox);
                                AxisAlignedBB prevAABB = ExtendedPlayer.get(player).prevAABB;
                                player.boundingBox.setBB(prevAABB);

                            }
                        }
После:

Java:
for (Object o : w.playerEntities) {
                            if (o instanceof EntityPlayer) {
                                EntityPlayer player = (EntityPlayer) o;
                                if(boxes.containsKey(player)) {
                                    player.boundingBox.setBB(boxes.get(player));
                                }
                            }
                        }
 
1,196
31
183
Чота допереть не могу совсем.
Сетаю вот так в тикере каждую секунду
Java:
if(player.ticksExisted % 20 == 0 ) {
           player.refreshDisplayName();
           if(!player.worldObj.isRemote) {
           System.out.println("Предыдущий "+prevAABB);
           System.out.println("Текущий "+player.boundingBox);
           this.prevAABB = player.boundingBox.copy();
           }
       }
Потестил побегал на шифте, координаты отличаются у боксов на 5-6 блоков (это за секунду чел столько пробегает)
Но на серваке чота все равно надо стрелять с упреждением как и ранее... (это я тестил с другом)
Если что, вот код
Пытался стрелять четко в модель игрока - не детектит попадание...
Это походу единственная проблема с которой я не могу справится со своими мозгами :D
 

tox1cozZ

aka Agravaine
8,455
598
2,892
Тебе не раз в секунду нужно это делать, а каждый тик. И у тебя должна быть не одна переменная которая меняется раз в секунду, а массив "истории", размер которого равен количеству предыдущих тиков истории.
Что-то типа такого, я не помню уже:
Java:
AxisAlignedBB[] states = new AxisAlignedBB[20]; // 20 тиков истории
int currentStateIndex;

update(){
    if(currentStateIndex >= states.length){
        currentStateIndex = 0;
    }

    states[currentStateIndex++] = player.boundingBox.copy();
}

checkHit(){
    AxisAlignedBB currentState = states[player.ping / 20];
    AxisAlignedBB box = player.boundingBox.copy();
    player.boundingBox.setBB(currentState);
    // raycast
    player.boundingBox.setBB(box);
}
 
Последнее редактирование:
1,196
31
183
Пожалуй, пока поставлю лучший ответ, думаю, ты лучший в этой сфере ❤
И еще вот тут
Java:
if(currentStateIndex >= states.length){
        currentStateIndex = 0;
    }
Надо поменять на ++currentStateIndex в проверке же да, а то я туплю ару
 
Последнее редактирование:
Сверху