Перейти к содержанию
Aeros

НПС репликами спамят в систем чат.

Рекомендуемые сообщения

Доброго времени суток!

Возник новый вопрос, может сможете что-то посоветовать.
НПС (ивентовые и которые в городах) периодически произносят различные реплики, пишут они их в белый локал чат. Это нормально.
Во всех вкладках чата, в настройках, можно выставить отображение "Основного" чата (тот самый локал). В данном случае (на скрине), в нижнем чате разрешены любые сообщения, а в верхнем - только "системные сообщения, урон и предметы" (все стандартно).

Проблема в том,  что, как бы это сказать, сервер определяет реплики НПС (на скрине это Реми и Мастер Йода), как системные сообщения и кидает их (в том числе) в систем чат. И эти сообщения в систем чате никак не скрыть (можно только полностью заглушить реплики НПС).
Звучит бредово, согласен. На других серверах, с этим же клиентом и с этим же SystemMsg.dat, все нормально. Видимо проблема на стороне этого сервера. Но где искать?

З.Ы. Сервер EmuRT l2p от 01.15.2016 (если это важно).

1133719216_.png.36a7cf6a8b0744ab7369924c61c04bc7.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Скорее проблема все же в патче или в настройках отображения.

Поиграйтесь ещё с патчем.

Так же если есть исходники, можете глянуть там

  • Upvote 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
27 минут назад, PrimeDev сказал:

Скорее проблема все же в патче или в настройках отображения.

Поиграйтесь ещё с патчем.

Так же если есть исходники, можете глянуть там

Спасибо за ответ.

Нет, дело не в патче, все перепроверил. Чистый клиент, родной SystemMsg.dat . На других серверах (имеется парочка под рукой) проверял - все работает правильно, без каких либо дополнительных манипуляций.
А тут, сообщения от НПС (в обязательном порядке) , которые помечены как "npcSay" (что предполагает локал чат) идут в систем чат. Именно ТОЛЬКО сообщения от НПС. Если игрок пишет в локал чат, его сообщения обрабатываются правильно и не попадают в систем чат.

Сижу голову ломаю, провел сейчас небольшой эксперимент.
Подменил в gameserver\data\scripts\ai\Remy.java (НПС Реми, который у меня выше на скрине), в строчке
"Functions.npcSay(actor, NpcString.A_DELIVERY_FOR_MR);" параметр "npcSay" на "npcShout" (предполагая, что непись начнет кричать эту фразу в оранжевый чат (Shout) вместо локала).
И действительно, эту фразу НПС стал слать не в локал, а в шаут, А САМОЕ ИНТЕРЕСНОЕ, что в этом случае, его сообщения обрабатываются правильно и не попадают в систем чат.

Из вышесказанного делаю вывод, что у сервера проблема только с сообщениями от НПС и только с теми, которые помечены для локал чата.
Сервер определяет их (почему-то) как системные и (естественно) отправляет их в систем чат. Такая вот история.

Исходники есть, но там сам шут ногу сломит. Сижу вот роюсь, не зная толком что ищу :unknw:

818048886_.png.5b42e204ca7f7fad7d905efcf95648de.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хах. Выяснилась новая интересная подробность!
НПС отправляют свои сообщения не в систем чат, как я думал ранее, они их просто отправляют... Куда-то...(?)

Поясню. Если, в настройках чата, отключить систем чат, основной чат (он же локал), если даже вообще все чаты выключить, вообще все возможные, то сообщения от НПС идут в чат все равно. Видимо сервер не понимает как их классифицировать. Чудо-чудное.
Пока только одно решение нашел - поставить галочку в пункте "Отключить слова NPC", но это как-то странно все.
Может есть еще какие-то идеи?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

они скорее всего шлют в тип чата NPC_SAY (тип 22) [еще есть NPC_SHOUT (тип 23)] и вот я не помню была ли в хф возможность выключить в настройках именно эти типы чата.

Под рукой сервера и клиента хф нет, но в более новых хрниках это вот это вот.

YpMFZDR.png

Изменено пользователем Gaikotsu
  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
22 минуты назад, Gaikotsu сказал:

они скорее всего шлют в тип чата NPC_SAY (тип 22) [еще есть NPC_SHOUT (тип 23)] и вот я не помню была ли в хф возможность выключить в настройках именно эти типы чата.

Под рукой сервера и клиента хф нет, но в более новых хрниках это вот это вот.

А вот это похоже на правду, да.
У меня обычный клиент ХФ и там нет возможности отключать "Реплики NPC" по отдельным каналам (как на вашем скрине), там есть только "Отключить слова NPC" (скрин) и работает оно на все каналы сразу (либо с ними - на всех каналах, либо без них вообще).
Предположу, что затачивали сервер под клиент с интерфейсом от более поздних хроник и будь у меня такой клиент, проблема бы решалась просто галочкой в нужном канале.

А есть какая-то возможность перевести их реплики из темно-серого чата (реплики NPC) в белый (основной)? Может костыль какой-то?

Готов даже, самым разговорчивым НПС, прописать ручками Functions.npcSay на что-то другое. Но пока только нашел:

npcSay (белый, который у меня темно-серый, он же "Реплики NPC") npcSayToPlayer (фиолетовый, он же "Шепот") и npcShout (оранжевый, он же "Крик").


123030709_.JPG.9116d4853a493c19e9de501cde33809b.JPG

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ну так вот именно в методах npcSay и должен указваться тип чата - метод по идее вызвает пакет NpcSay, в котром указывается в каком виде чата показать сообщение от нпс.

Выглядит он примерно так, в _type как раз шлется тип чата.

Спойлер

package l2p.gameserver.network.s2c;

import l2p.gameserver.enums.ChatType;
import l2p.gameserver.model.instances.NpcInstance;
import l2p.gameserver.network.components.NpcString;
import l2p.gameserver.network.components.ServerPackets;

public class NpcSay extends AbstractNpcString
{
	private int _objId;
	private int _type;
	private int _id;
	private int _fStringId;

	public NpcSay(NpcInstance npc, ChatType chatType, String text)
	{
		this(npc, chatType, NpcString.NONE, text);
	}

	public NpcSay(NpcInstance npc, ChatType chatType, int fStringId, String... args)
	{
		this(npc, chatType, NpcString.NONE, fStringId, args);
	}

	public NpcSay(NpcInstance npc, ChatType chatType, NpcString npcString, String... args)
	{
		this(npc, chatType, npcString, 0, args);
	}

	public NpcSay(NpcInstance npc, ChatType chatType, NpcString npcString, int fstringId, String... args)
	{
		super(npcString, args);
		_objId = npc.getObjectId();
		_id = npc.getId();
		_type = chatType.ordinal();
		_fStringId = fstringId;
	}

	@Override
	protected final void writeImpl()
	{
		writeId(ServerPackets.NPC_SAY);
		writeD(_objId);
		writeD(_type);
		writeD(1000000 + _id);

		if (_fStringId == 0)
			writeElements();
		else
			writeElements(_fStringId);
	}
}

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
12 часов назад, Gaikotsu сказал:

ну так вот именно в методах npcSay и должен указваться тип чата - метод по идее вызвает пакет NpcSay, в котром указывается в каком виде чата показать сообщение от нпс.

Выглядит он примерно так, в _type как раз шлется тип чата.

  NpcSay (Показать контент)


package l2p.gameserver.network.s2c;

import l2p.gameserver.enums.ChatType;
import l2p.gameserver.model.instances.NpcInstance;
import l2p.gameserver.network.components.NpcString;
import l2p.gameserver.network.components.ServerPackets;

public class NpcSay extends AbstractNpcString
{
	private int _objId;
	private int _type;
	private int _id;
	private int _fStringId;

	public NpcSay(NpcInstance npc, ChatType chatType, String text)
	{
		this(npc, chatType, NpcString.NONE, text);
	}

	public NpcSay(NpcInstance npc, ChatType chatType, int fStringId, String... args)
	{
		this(npc, chatType, NpcString.NONE, fStringId, args);
	}

	public NpcSay(NpcInstance npc, ChatType chatType, NpcString npcString, String... args)
	{
		this(npc, chatType, npcString, 0, args);
	}

	public NpcSay(NpcInstance npc, ChatType chatType, NpcString npcString, int fstringId, String... args)
	{
		super(npcString, args);
		_objId = npc.getObjectId();
		_id = npc.getId();
		_type = chatType.ordinal();
		_fStringId = fstringId;
	}

	@Override
	protected final void writeImpl()
	{
		writeId(ServerPackets.NPC_SAY);
		writeD(_objId);
		writeD(_type);
		writeD(1000000 + _id);

		if (_fStringId == 0)
			writeElements();
		else
			writeElements(_fStringId);
	}
}

 

 

Нашел ChatType.java , NpcSay.java , Say2.java

ChatType.java

Спойлер

package l2p.gameserver.serverpackets.components;

/**
 * @author VISTALL
 * @date 12:48/29.12.2010
 */
public enum ChatType {

    ALL, //0
    SHOUT, //1    !
    TELL, //2    "
    PARTY, //3   #
    CLAN, //4    @
    GM, //5
    PETITION_PLAYER, //6   used for petition
    PETITION_GM, //7   * used for petition
    TRADE, //8  +
    ALLIANCE, //9   $
    ANNOUNCEMENT, //10
    SYSTEM_MESSAGE, //11
    L2FRIEND,
    MSNCHAT,
    PARTY_ROOM, //14
    COMMANDCHANNEL_ALL, //15 ``
    COMMANDCHANNEL_COMMANDER, //16  `
    HERO_VOICE, //17 %
    CRITICAL_ANNOUNCE, //18
    SCREEN_ANNOUNCE,
    BATTLEFIELD, //20   ^
    MPCC_ROOM,  //21 добавлен в епилоге, подобия PARTY_ROOM ток для СС
    NPC_ALL,  // 22 добавлен в ХФ, аналог  ALL, но может игнорироватся клиентом
    NPC_SHOUT;  // 23 добавлен в ХФ, аналог  SHOUT, но может игнорироватся клиентом
    public static final ChatType[] VALUES = values();
}

 


NpcSay.java
 

Спойлер

package l2p.gameserver.serverpackets;

import l2p.gameserver.model.instances.NpcInstance;
import l2p.gameserver.serverpackets.components.ChatType;
import l2p.gameserver.serverpackets.components.NpcString;

public class NpcSay extends NpcStringContainer {

    private int _objId;
    private int _type;
    private int _id;

    public NpcSay(NpcInstance npc, ChatType chatType, String text) {
        this(npc, chatType, NpcString.NONE, text);
    }

    public NpcSay(NpcInstance npc, ChatType chatType, NpcString npcString, String... params) {
        super(npcString, params);
        _objId = npc.getObjectId();
        _id = npc.getNpcId();
        _type = chatType.ordinal();
    }

    @Override
    protected final void writeImpl() {
        writeC(0x30);
        writeD(_objId);
        writeD(_type);
        writeD(1000000 + _id);
        writeElements();
    }
}

Say2.java

Спойлер

package l2p.gameserver.serverpackets;

import l2p.gameserver.model.Player;
import l2p.gameserver.serverpackets.components.ChatType;
import l2p.gameserver.serverpackets.components.NpcString;
import l2p.gameserver.serverpackets.components.SysString;
import l2p.gameserver.serverpackets.components.SystemMsg;

public class Say2 extends NpcStringContainer {

    private ChatType _type;
    private SysString _sysString;
    private SystemMsg _systemMsg;
    private int _objectId;
    private String _charName, _text;

    public Say2(int objectId, ChatType type, SysString st, SystemMsg sm) {
        super(NpcString.NONE);
        _objectId = objectId;
        _type = type;
        _sysString = st;
        _systemMsg = sm;
    }

    public Say2(int objectId, ChatType type, String charName, String text) {
        this(objectId, type, charName, NpcString.NONE, text);
    }

    public Say2(int objectId, ChatType type, String charName, NpcString npcString, String... params) {
        super(npcString, params);
        _objectId = objectId;
        _type = type;
        _charName = charName;
        _text = params[0];
    }

    @Override
    protected final void writeImpl() {
        writeC(0x4A);
        writeD(_objectId);
        writeD(_type.ordinal());
        switch (_type) {
            case SYSTEM_MESSAGE:
                writeD(_sysString.getId());
                writeD(_systemMsg.getId());
                break;
            default:
                writeS(_charName);
                writeElements();
                break;
        }
        writeS(_text);

        Player player = getClient().getActiveChar();
        if (player != null) {
            player.broadcastSnoop(_type.ordinal(), _charName, _text);
        }
    }
}

еще встречал строчку типа
 

Спойлер

    public static void sayToAll(String address, String[] replacements) {
        Announcements.getInstance().announceByCustomMessage(address, replacements, ChatType.CRITICAL_ANNOUNCE);

но это, видимо, вообще из другой оперы...

Ну и понятно, что можно НПСам переписать "npcSay" на "npcSayToPlayer" или "npcShout", а вот дальше - для меня темный лес.

Если верить ChatType.java и Functions.java, то НПС, в своих сообщениях, используют NPC_ALL,  // 22, как Вы и предполагали ранее.
А как НПС (хотя бы определенных) заставить "говорить" на ALL, //0 , я не въезжаю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ну так в Functions.npcSay  как раз и должно указываться в каком типе чата говорить

к примеру у меня методы npcSay вызывают метод npcSayInRange, а в нем уже вызывает пакет NpcSay, в котором вторым параметром как раз и передается тип чата. Просто меняешь там в вызове ChatType.NPC_SAY на например ChatType.ALL и все.

блин, это же все самые основы...

Изменено пользователем Gaikotsu
  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
16 минут назад, Gaikotsu сказал:

ну так в Functions.npcSay  как раз и должно указываться в каком типе чата говорить

к примеру у меня методы npcSay вызывают метод npcSayInRange, а в нем уже вызывает пакет NpcSay, в котором вторым параметром как раз и передается тип чата. Просто меняешь там в вызове ChatType.NPC_SAY на например ChatType.ALL и все.

блин, это же все самые основы...

Огоромное спасибо, что находите время на ответы! К сожалению для меня это темный лес и я ничего в этом не понимаю, а если что-то и делаю, то исключительно методом научного тыка + мануалы в интернете (если такие там есть).

Я правильно Вас понял?
Захожу в Functions.java , нахожу все что связанно с локальным (былым чатом), ищу там строчки с "ChatType.NPC_ALL" и меняю их на "ChatType.ALL".

Вот у меня это кусок, вот так меняю (в двух местах)
 

Спойлер


    // Белый чат
    public static void npcSayInRange(NpcInstance npc, String text, int range) {
        npcSayInRange(npc, range, NpcString.NONE, text);
    }

    // Белый чат
    public static void npcSayInRange(NpcInstance npc, int range, NpcString fStringId, String... params) {
        if (npc == null) {
            return;
        }
        NpcSay cs = new NpcSay(npc, ChatType.ALL, fStringId, params);  // -----------------------------------------------------------------  тут было ChatType.NPC_ALL
        for (Player player : World.getAroundPlayers(npc, range, Math.max(range / 2, 200))) {
            if (npc.getReflection() == player.getReflection()) {
                player.sendPacket(cs);
            }
        }
    }

    // Белый чат
    public static void npcSay(NpcInstance npc, String text) {
        npcSayInRange(npc, text, 1500);
    }

    // Белый чат
    public static void npcSay(NpcInstance npc, NpcString npcString, String... params) {
        npcSayInRange(npc, 1500, npcString, params);
    }

    // Белый чат
    public static void npcSayInRangeCustomMessage(NpcInstance npc, int range, String address, Object... replacements) {
        if (npc == null) {
            return;
        }
        for (Player player : World.getAroundPlayers(npc, range, Math.max(range / 2, 200))) {
            if (npc.getReflection() == player.getReflection()) {
                player.sendPacket(new NpcSay(npc, ChatType.ALL, new CustomMessage(address, player, replacements).toString())); // -------- тут было ChatType.NPC_ALL
            }
        }
    }

    // Белый чат
    public static void npcSayCustomMessage(NpcInstance npc, String address, Object... replacements) {
        npcSayInRangeCustomMessage(npc, 1500, address, replacements);
    }

 

Правильно?

И собираю сервер с уже отредактированным Functions.java?

Или можно как-то подсунуть серверу отредактированный Functions.java, чтоб несобирать заново?

А в файлах AI (того же Реми, для примера), нужно переписывать строчки с
"Functions.npcSay" на "Functions.npcSayInRange" или на "Functions.npcSayInRangeCustomMessage".
Или AI НПС трогать вообще не нужно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
11 часов назад, Aeros сказал:

И собираю сервер с уже отредактированным Functions.java?

Или можно как-то подсунуть серверу отредактированный Functions.java, чтоб несобирать заново?

Можно конечно один класс чисто компильнуть и в jar заменить, но я задолбаюсь как это делать объяснять ибо это не так просто - в двух словах не объяснить.

11 часов назад, Aeros сказал:

А в файлах AI (того же Реми, для примера), нужно переписывать строчки с
"Functions.npcSay" на "Functions.npcSayInRange" или на "Functions.npcSayInRangeCustomMessage".
Или AI НПС трогать вообще не нужно?

не нужно, после твоей правки все нпс что говорят через вызов Functions.npcSay уже будут говорить в общий чат.

 

---

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

Изменено пользователем Gaikotsu
  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
3 часа назад, Gaikotsu сказал:

Можно конечно один класс чисто компильнуть и в jar заменить, но я задолбаюсь как это делать объяснять ибо это не так просто - в двух словах не объяснить.

не нужно, после твоей правки все нпс что говорят через вызов Functions.npcSay уже будут говорить в общий чат.

---

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

Огромное Вам СПА-СИ-БО (в очередной раз)!!!
Понял, принял, пойду эксперименты экспериментировать!


---
Спасибо за совет.

Так и не было мыслей, изначально, в ядро лезть, тем более что-то там менять, компилировать его потом.
Наделся что решение где-то на поверхности.
А оказалось, что банальный чат вон куда заставил лезть. Это профессионалу - ерунда, а по моим познаниям конечно овер до хрена сложная задача...
Но благодаря Вам, все стало гораздо понятней!
Заодно процесс компиляции попытаюсь освоить (есть стимул теперь), чего пытался всячески избегать, так сказать от греха.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...