GC -> Classic

Psycho

Просветленный
Легенда
Орден Золотого Заката
Победитель в номинации 2023
Победитель в номинации 2022
Победитель в номинации 2021
Участник Новогоднего Фонда 2021
Неукротимое пламя
Старожил II степени
Победитель в номинации 2020
Победитель в номинации 2019
Знаток великого письма
Знаток письма
Веселый флудер
Мастер реакций
Любитель реакций
Знаток Lineage2
Старожил I степени
Победитель в номинации 2017
Победитель в номинации 2016
Медаль за активность на Форуме
За веру и верность форуму
Сообщения
4 491
Розыгрыши
1
Решения
3
Репутация
4 352
Реакции
2 843
Баллы
2 438
Зайти на классик то я зашел, но это прям удивило.))
Какие пакеты нужно править чтобы это починить, есть инфа?
Видно только один баф с вечными 0 сек.
Shot00000.jpg
В изучении вообще шик.
Shot00002.jpg

Сурсы: L2JUnity
 
в помощь, где то на l2j форуме был скрипт снифа спаунов.
Добавив проверку принадлежности точки к полигону - можно сделать вполне себе достойные спауны (не статик).
Вот сам скрипт (l2jserver не открывается почему-то, в кеше нашел), его нужно переделать немного либо написать свой.
Код:
/*
 * Copyright (c) 2012-2015, RaveN Network INC. and/or its affiliates. All rights reserved.
 * RAVEN NETWORK INC. PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 * Licensed Materials - Property of RaveN Network INC.
 * Restricted Rights - Use, duplication or disclosure restricted.
 */
package internal.generator;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Future;
import java.util.regex.Pattern;

import javolution.util.FastMap;

import org.apache.commons.lang3.StringUtils;

import util.packet.CommonPacketSender;

import net.l2emuproject.proxy.network.game.client.L2GameClient;
import net.l2emuproject.proxy.network.game.server.L2GameServer;
import net.l2emuproject.proxy.network.meta.RandomAccessMMOBuffer;
import net.l2emuproject.proxy.network.meta.field.EnumeratedPayloadField;
import net.l2emuproject.proxy.script.ScriptFieldAlias;
import net.l2emuproject.proxy.script.game.InteractiveChatCommands;
import net.l2emuproject.proxy.script.game.PpeEnabledGameScript;
import net.l2emuproject.proxy.script.packets.InvalidPacketWriterArgumentsException;
import net.l2emuproject.proxy.state.entity.ObjectInfo;
import net.l2emuproject.proxy.state.entity.ObjectLocation;
import net.l2emuproject.proxy.state.entity.cache.ObjectInfoCache;
import net.l2emuproject.proxy.state.entity.context.ICacheServerID;
import net.l2emuproject.proxy.state.entity.type.NonPlayerControllable;
import net.l2emuproject.proxy.state.entity.type.ObjectType;
import net.l2emuproject.proxy.ui.savormix.io.base.IOConstants;
import net.l2emuproject.script.util.HasScriptDependencies;
import net.l2emuproject.util.L2Collections;
import net.l2emuproject.util.concurrent.L2ThreadPool;
import net.l2emuproject.util.logging.L2Logger;

/**
 * A basic spawn list generator for non-moving NPCs.
 * <B>The operator of this script must ensure</B> that the state is only saved after it was made sure
 * that all NPC walkers that ever were in knownlist range have moved at least once (or have attacked
 * something).
 * However, alternative measures should be taken to ensure that stationary guards were not distracted
 * by aggressive or negative reputation players.
 *
 * @author _dev_
 */
@HasScriptDependencies("util.packet.CommonPacketSender")
public class FixedSpawnGenerator extends PpeEnabledGameScript implements InteractiveChatCommands, IOConstants
{
    static final L2Logger LOG = L2Logger.getLogger(FixedSpawnGenerator.class);
    static final Pattern NAME_TRIM = Pattern.compile("(?:[0-9]+: )|(?:\\[not named in client\\])|(?: \\[NPC\\])");
  
    @ScriptFieldAlias
    private static final String NPC_OID = "fspawn_gen_npc_oid";
    @ScriptFieldAlias
    private static final String NPC_ATTACKABLE = "fspawn_gen_npc_atk";
    @ScriptFieldAlias
    private static final String WALKER_OID = "fspawn_walker_oid";
  
    static final Path OUTPUT_ROOT = DATA_MINING_DIRECTORY.resolve("spawn_data");
  
    //private final FastMap<ICacheServerID, ServerSpawns> _data;
    // mapping by client results in better interactivity
    private final FastMap<L2GameClient, ServerSpawns> _data;
  
    private volatile Future<?> _saveTask;
  
    /** Constructs this script. */
    public FixedSpawnGenerator()
    {
        //_data = new FastMap<ICacheServerID, ServerSpawns>().setShared(true);
        _data = new FastMap<L2GameClient, ServerSpawns>().setShared(true);
    }
  
    @Override
    public void handleDisconnection(L2GameClient client)
    {
        _data.remove(client);
    }
  
    @Override
    public void handleClientPacket(final L2GameClient client, L2GameServer server, RandomAccessMMOBuffer buf) throws RuntimeException
    {
        String msg = buf.readFirstString(CHAT_COMMAND);
      
        if ("\\\\fs_reset".equals(msg))
        {
            _data.put(client, new ServerSpawns());
            try
            {
                CommonPacketSender.sendChatMessage(client, 5, "SYS", "Spawn generator state cleared.");
            }
            catch (InvalidPacketWriterArgumentsException e)
            {
                LOG.warn("", e);
            }
            return;
        }
      
        if (!"\\\\fs_save".equals(msg))
            return;
      
        if (_saveTask != null && !_saveTask.isDone())
        {
            try
            {
                CommonPacketSender.sendChatMessage(client, 5, "SYS", "A state save is already in progress.");
            }
            catch (InvalidPacketWriterArgumentsException e)
            {
                LOG.warn("", e);
            }
            return;
        }
      
        final ICacheServerID context = getEntityContext(server);
        //final ServerSpawns spawns = _data.get(context);
        final ServerSpawns spawns = _data.get(client);
        if (spawns == null)
            return;
      
        try
        {
            CommonPacketSender.sendChatMessage(client, 5, "SYS", "Saving " + spawns._fixedSpawns.size() + " static NPC spawns to disk.");
        }
        catch (InvalidPacketWriterArgumentsException e)
        {
            LOG.warn("", e);
            // not a big deal if no message was sent; continue
        }
      
        _saveTask = L2ThreadPool.submitLongRunning(new Runnable()
        {
            @Override
            public void run()
            {
                final Path dir = OUTPUT_ROOT.resolve(String.valueOf(client.getProtocol().getVersion()));
                try
                {
                    Files.createDirectories(dir);
                  
                    try (final BufferedWriter bw = Files.newBufferedWriter(dir.resolve("walkers_" + System.currentTimeMillis() + ".txt"), Charset.forName("UTF-8")))
                    {
                        for (final Integer npc : spawns._walkerNPCs)
                            bw.append(String.valueOf(npc)).append("\r\n");
                    }
                  
                    try (final BufferedWriter bw = Files.newBufferedWriter(dir.resolve("spawns_" + System.currentTimeMillis() + ".xml"), Charset.forName("UTF-8")))
                    {
                        bw.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>").append("\r\n\r\n");
                        bw.append("<list xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"../../templates/spawnlist.xsd\">");
                        bw.append("\r\n");
                      
                        final Map<Integer, String> npcNames = new HashMap<>();
                        final Map<Integer, Set<ObjectLocation>> locByNPC = new TreeMap<>();
                      
                        final ObjectInfoCache cache = ObjectInfoCache.getInstance();
                        for (final Entry<Integer, ObjectLocation> e : spawns._fixedSpawns.entrySet())
                        {
                            final ObjectInfo oi = cache.getOrAdd(e.getKey(), context);
                            final ObjectLocation initial = e.getValue(), current = oi.getLocation();
                            if (!initial.equals(current))
                            {
                                if (initial.getX() != current.getX() || initial.getY() != current.getY() || initial.getZ() != current.getZ())
                                {
                                    LOG.info("OH NO IT'S A WALKER " + oi);
                                    LOG.info("Current: " + current + ", old: " + initial);
                                }
                                else
                                    LOG.info("Heading mismatch! Initial: " + initial.getHeading() + ", current: " + current.getHeading() + " for " + oi);
                                continue;
                            }
                          
                            final ObjectType type = oi.getType();
                            if (!(type instanceof NonPlayerControllable))
                            {
                                LOG.info("OH NO IT'S NOT A NPC " + oi);
                                continue;
                            }
                          
                            final Integer npc = ((NonPlayerControllable)type).getTemplateID();
                            if (spawns._walkerNPCs.contains(npc))
                                continue;
                          
                            if (!npcNames.containsKey(npc))
                                npcNames.put(npc, NAME_TRIM.matcher(oi.toString()).replaceAll(""));
                          
                            Set<ObjectLocation> locations = locByNPC.get(npc);
                            if (locations == null)
                            {
                                locations = new TreeSet<>(new LocationOrder());
                                locByNPC.put(npc, locations);
                            }
                            locations.add(initial);
                        }
                      
                        for (final Entry<Integer, Set<ObjectLocation>> e : locByNPC.entrySet())
                        {
                            bw.append("\t<spawn npcId=\"").append(e.getKey().toString()).append("\">\r\n");
                            final String name = npcNames.get(e.getKey());
                            if (!StringUtils.isEmpty(name))
                                bw.append("\t\t<!-- ").append(name).append(" -->\r\n");
                            for (final ObjectLocation loc : e.getValue())
                            {
                                bw.append("\t\t<location x=\"").append(String.valueOf(loc.getX())).append("\" y=\"");
                                bw.append(String.valueOf(loc.getY())).append("\" z=\"").append(String.valueOf(loc.getZ()));
                                bw.append("\" heading=\"").append(String.valueOf(loc.getHeading())).append("\" />\r\n");
                            }
                            bw.append("\t</spawn>\r\n");
                        }
                        bw.append("</list>\r\n");
                    }
                }
                catch (IOException e)
                {
                    LOG.error("Cannot save NPC spawns.", e);
                    return;
                }
              
                try
                {
                    CommonPacketSender.sendChatMessage(client, 5, "SYS", "NPC spawns saved to disk.");
                }
                catch (InvalidPacketWriterArgumentsException e)
                {
                    LOG.warn("", e);
                    // not a big deal if no message was sent
                }
            }
        });
    }
  
    @Override
    public void handleServerPacket(L2GameClient client, L2GameServer server, RandomAccessMMOBuffer buf) throws RuntimeException
    {
        removeWalker:
        {
            final EnumeratedPayloadField oid = buf.getSingleFieldIndex(WALKER_OID);
            if (oid == null)
                break removeWalker;
          
            final ICacheServerID context = getEntityContext(server);
            //ServerSpawns spawns = _data.get(context);
            ServerSpawns spawns = _data.get(client);
            if (spawns == null)
                spawns = L2Collections.putIfAbsent(_data, client, new ServerSpawns());
            //    spawns = L2Collections.putIfAbsent(_data, context, new ServerSpawns());
          
            final Integer objectID = buf.readInteger32(oid);
            if (spawns._fixedSpawns.remove(objectID) == null)
                return;
          
            final ObjectInfo oi = ObjectInfoCache.getInstance().getOrAdd(objectID, context);
            final ObjectType type = oi.getType();
            if (!(type instanceof NonPlayerControllable))
                return;
          
            final NonPlayerControllable template = (NonPlayerControllable)type;
            spawns._walkerNPCs.add(template.getTemplateID());
            return;
        }
        addSpawn:
        {
            final EnumeratedPayloadField oid = buf.getSingleFieldIndex(NPC_OID);
            final EnumeratedPayloadField atk = buf.getSingleFieldIndex(NPC_ATTACKABLE);
            if (oid == null || atk == null)
                break addSpawn;
          
            final ICacheServerID context = getEntityContext(server);
            //ServerSpawns spawns = _data.get(context);
            ServerSpawns spawns = _data.get(client);
            if (spawns == null)
                spawns = L2Collections.putIfAbsent(_data, client, new ServerSpawns());
            //    spawns = L2Collections.putIfAbsent(_data, context, new ServerSpawns());
          
            final Integer objectID = buf.readInteger32(oid);
            final boolean hostile = buf.readInteger32(atk) != 0;
            if (hostile || !spawns._ignoredOIDs.add(objectID))
                return;
          
            final ObjectInfo oi = ObjectInfoCache.getInstance().getOrAdd(objectID, context);
            if (!(oi.getType() instanceof NonPlayerControllable))
                return;
          
            if (spawns._fixedSpawns.remove(objectID) != null)
            {
                LOG.info("Constraint violation for " + oi);
                return;
            }
          
            spawns._fixedSpawns.put(objectID, oi.getLocation());
            return;
        }
    }
  
    @Override
    public String getName()
    {
        return "NPC spawn gen (static)";
    }
  
    private static final class LocationOrder implements Comparator<ObjectLocation>
    {
        LocationOrder()
        {
        }
      
        @Override
        public int compare(ObjectLocation o1, ObjectLocation o2)
        {
            int diff = o1.getZ() - o2.getZ();
            if (diff != 0)
                return diff;
          
            diff = o1.getY() - o2.getY();
            if (diff != 0)
                return diff;
          
            diff = o1.getX() - o2.getX();
            if (diff != 0)
                return diff;
          
            diff = o1.getHeading() - o2.getHeading();
            if (diff != 0)
                return diff;
          
            return 0;
        }
    }
  
    private static final class ServerSpawns
    {
        final Set<Integer> _ignoredOIDs;
        final Map<Integer, ObjectLocation> _fixedSpawns;
        final Set<Integer> _walkerNPCs;
      
        ServerSpawns()
        {
            _fixedSpawns = new FastMap<Integer, ObjectLocation>().setShared(true);
            _ignoredOIDs = new CopyOnWriteArraySet<Integer>();
            _walkerNPCs = new CopyOnWriteArraySet<Integer>();
        }
    }
}
 

В классике структура пакетов немного другая )
Если речь идет о 2-ух версиях одного протокола, структура у пакетов идентичная.

Если кому то нужна структура пакетов 140 протокола пишите в лс
 
Назад
Сверху Снизу