NetPro: Packet Analysis and Visualization tool

Have you created a useful tool? or Do you want to get help building one? This is the right place!
Forum rules
READ NOW: L2j Forums Rules of Conduct
Post Reply
ChaosPaladin
Posts: 39
Joined: Wed Feb 19, 2014 12:13 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by ChaosPaladin »

Do someone have a script to get spawnlist from packet NpcInfo/ExNpcInfo ? :P
SaveGame
Posts: 121
Joined: Thu Oct 30, 2014 9:54 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by SaveGame »

This will SPECIFICALLY extract all NON-MOVING NPC spawn locations and yaws (headings). Of course, some mutually interacting NPCs seem to change their heading from time to time (I think that's a part of their AI script). However, these are generally only in some special locations, even though there is one or two in the new TI).

Makes use on script aliases already present within packet definitions (personally I last tested this back in Valiance, before the incremental definition loading; but I hope the ertheian definitions have also had the missing aliases added by now).

You may not use this script to gather monster locations, basically because they never respawn in the same spot on official servers.

Code: Select all

/*
 * 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>();
		}
	}
}
P.S. This was made on request quite some time ago, so you might need to tune the output generation to suit your own needs.
Image
ChaosPaladin
Posts: 39
Joined: Wed Feb 19, 2014 12:13 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by ChaosPaladin »

Well, thank you. I will try to use it

upd:

After download new version, i dont see GameSever connection in NA

Image
SaveGame
Posts: 121
Joined: Thu Oct 30, 2014 9:54 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by SaveGame »

ChaosPaladin wrote:Well, thank you. I will try to use it

upd:

After download new version, i dont see GameSever connection in NA

Image
Thanks for the report.

I could not reproduce this on my development machine, but I use a relatively large serviceconfig.xml there. After opening NP on another computer with the default config I could reproduce this issue.

Until the next release, please change the default gameWorldSocket to

Code: Select all

<gameWorldSocket ip="127.0.0.1" port="7776" />
It is just an oversight related to ints. After all, shifting an int value by 32 bits to either direction doesn't change the value.
Image
SaveGame
Posts: 121
Joined: Thu Oct 30, 2014 9:54 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by SaveGame »

A new release is now available, this time with JavaDoc (see the original post).

This marks yet another step towards preparing NP for open source. Slowly getting there :)

P.S. Ironically, JavaDoc for -commons-scripts is not provided. The component will be open sourced soon (luckily, it's a standalone).
P.P.S. JavaDoc for -commons is not provided. This component is one of the larger issues in the way of making NP open source, and I do not have a suitable way to deal with it for now.
Image
SaveGame
Posts: 121
Joined: Thu Oct 30, 2014 9:54 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by SaveGame »

A new [pre]release is now out, mainly IO support with some minor fixes. Still have to deal with 1.5 (yes, that's one and a half) dependencies before it will be possible to opensource the application. I already know what will be needed and what will have to change once things are set in motion, so it should not take too long after that. I'll keep you guys notified about any further developments.

In the meantime, I'll still be providing routine releases such as this one. Have fun 8)
Image
michael1414
Posts: 10
Joined: Sun Apr 27, 2014 12:17 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by michael1414 »

Hi.
In Attachement I added diff for: CharacterSelectionInfo.xml
CharacterSelectionInfo.zip
You do not have the required permissions to view the files attached to this post.
SaveGame
Posts: 121
Joined: Thu Oct 30, 2014 9:54 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by SaveGame »

michael1414 wrote:Hi.
In Attachement I added diff for: CharacterSelectionInfo.xml
CharacterSelectionInfo.zip
Thank you, I'll make sure to apply it to all versions of this packet starting from the first client with armor enchant glows.
Image
michael1414
Posts: 10
Joined: Sun Apr 27, 2014 12:17 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by michael1414 »

Hi.
Next changes for: CharacterSelectionInfo.xml

PS: Would be chance to add this xml files to github or any other server ? Would be much easier to making changes in that files.
You do not have the required permissions to view the files attached to this post.
SaveGame
Posts: 121
Joined: Thu Oct 30, 2014 9:54 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by SaveGame »

michael1414 wrote:Hi.
Next changes for: CharacterSelectionInfo.xml

PS: Would be chance to add this xml files to github or any other server ? Would be much easier to making changes in that files.
See https://bitbucket.org/_dev_/netpro or directly here.
Image
ffsaga
Posts: 2
Joined: Tue Mar 31, 2009 6:53 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by ffsaga »

Code: Select all

INFO [2015-06-30 01:32:41.167 +0800] ShutdownManager: ShutdownHook: Initialized.
INFO [2015-06-30 01:32:41.167 +0800] DeadlockDetector: DeadlockDetector: Initialized.
INFO [2015-06-30 01:32:41.213 +0800] NetProScriptLog: Initialized scripts -> script.cache
INFO [2015-06-30 01:32:41.213 +0800] NetProScriptLog: Loading compiled script cache from script.cache…
INFO [2015-06-30 01:32:41.213 +0800] NetProScriptLog: [VFS] script.cache is not present.
INFO [2015-06-30 01:32:41.213 +0800] VersionnedPacketTable: Loading packet declarations…
INFO [2015-06-30 01:32:41.291 +0800] VersionnedPacketTable: Total: 504 client packets and 722 server packets.
INFO [2015-06-30 01:32:41.291 +0800] VersionnedPacketTable: Loading protocol declarations…
INFO [2015-06-30 01:32:41.307 +0800] VersionnedPacketTable: Total: 2 login protocols and 54 game protocols.
INFO [2015-06-30 01:32:41.307 +0800] VersionnedPacketTable: Loading packet definitions…
INFO [2015-06-30 01:32:41.307 +0800] VersionnedPacketTable: Loading login packets…
INFO [2015-06-30 01:32:41.307 +0800] VersionnedPacketTable: Prelude PTS declares 3 client and 10 server packets.
SEVERE [2015-06-30 01:32:41.323 +0800] proxy.ui.savormix.io.EndpointPacketLoader.toStructureElement(): RequestLogin
net.l2emuproject.proxy.network.meta.exception.InvalidFieldValueInterpreterException: null(ASCII) cannot be cast to net.l2emuproject.proxy.network.meta.FieldValueInterpreter
        at net.l2emuproject.proxy.network.meta.container.MetaclassRegistry.getInterpreter(MetaclassRegistry.java:186)
        at net.l2emuproject.proxy.ui.savormix.io.EndpointPacketLoader.toStructureElement(EndpointPacketLoader.java:234)
        at net.l2emuproject.proxy.ui.savormix.io.EndpointPacketLoader.childrenOf(EndpointPacketLoader.java:172)
        at net.l2emuproject.proxy.ui.savormix.io.EndpointPacketLoader.visitFile(EndpointPacketLoader.java:140)
        at net.l2emuproject.proxy.ui.savormix.io.EndpointPacketLoader.visitFile(EndpointPacketLoader.java:69)
        at java.nio.file.Files.walkFileTree(Unknown Source)
        at java.nio.file.Files.walkFileTree(Unknown Source)
        at net.l2emuproject.proxy.ui.savormix.io.VersionnedPacketTable.loadConfig(VersionnedPacketTable.java:422)
        at net.l2emuproject.proxy.ui.savormix.io.VersionnedPacketTable.<init>(VersionnedPacketTable.java:85)
        at net.l2emuproject.proxy.ui.savormix.io.VersionnedPacketTable$SingletonHolder.<clinit>(VersionnedPacketTable.java:753)
        at net.l2emuproject.proxy.ui.savormix.io.VersionnedPacketTable.getInstance(VersionnedPacketTable.java:748)
        at net.l2emuproject.proxy.ui.savormix.loader.Loader$$Lambda$20/1032616650.run(Unknown Source)
        at net.l2emuproject.proxy.L2Proxy.main(L2Proxy.java:91)
        at net.l2emuproject.proxy.ui.savormix.loader.Loader.main(Loader.java:265)
SaveGame
Posts: 121
Joined: Thu Oct 30, 2014 9:54 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by SaveGame »

Code: Select all

NetProScriptLog: Loading compiled script cache from script.cache…
NetProScriptLog: [VFS] script.cache is not present.
Yeah, I am aware that the 1.0 release did not include a precompiled script cache. Therefore, you must either: * – JRE is a lightweight environment that does not include a java compiler (namely, programmatic access to it). Use a precompiled class cache if you don't want to install a JDK (or mess with PATHs).

P.S. I added the precompiled script cache as an optional download. Might have to start add version information in the filename for subsequent releases (for now, NP is on a monthly release cycle).
Image
ffsaga
Posts: 2
Joined: Tue Mar 31, 2009 6:53 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by ffsaga »

SaveGame wrote:

Code: Select all

NetProScriptLog: Loading compiled script cache from script.cache…
NetProScriptLog: [VFS] script.cache is not present.
Yeah, I am aware that the 1.0 release did not include a precompiled script cache. Therefore, you must either:
(Sorry for my english)
Thank you. put your script.cache, It started normally
Then I delete your script.cache, and edit NetPro_win.bat
edit @start /ABOVENORMAL javaw.exe to "C:\Program Files\Java\jdk1.8.0_xxx\bin\javaw.exe"
It started normally too. log:

Code: Select all

NFO [2015-06-30 03:07:41.719 +0800] ShutdownManager: ShutdownHook: Initialized.
INFO [2015-06-30 03:07:41.719 +0800] DeadlockDetector: DeadlockDetector: Initialized.
INFO [2015-06-30 03:07:41.797 +0800] NetProScriptLog: Initialized scripts -> script.cache
INFO [2015-06-30 03:07:41.797 +0800] NetProScriptLog: Loading compiled script cache from script.cache…
INFO [2015-06-30 03:07:41.797 +0800] NetProScriptLog: [VFS] script.cache is not present.
INFO [2015-06-30 03:07:41.797 +0800] NetProScriptLog: Traversing scripts…
INFO [2015-06-30 03:07:41.797 +0800] NetProScriptLog: Indexing scripts in scripts…
INFO [2015-06-30 03:07:41.812 +0800] NetProScriptLog: Indexing scripts in scripts\condition…
INFO [2015-06-30 03:07:41.812 +0800] NetProScriptLog: Indexing scripts in scripts\condition\airship…
INFO [2015-06-30 03:07:41.812 +0800] NetProScriptLog: Indexing scripts in scripts\condition\equip…
INFO [2015-06-30 03:07:41.812 +0800] NetProScriptLog: Indexing scripts in scripts\condition\event…
rocknowx
Posts: 5
Joined: Sun Jul 12, 2015 11:31 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by rocknowx »

Duplicate File:
1.1\config\packets\gracia_final\client\RequestRecipeShopMakeItem.xml
packet id="CM_REQ_RECIPE_SHOP_MAKE_DO"

But already there have a
1.1\config\packets\c2_age_of_splendor\client\RequestRecipeShopMakeDo.xml
packet id="CM_REQ_RECIPE_SHOP_MAKE_DO"
SaveGame
Posts: 121
Joined: Thu Oct 30, 2014 9:54 pm

Re: NetPro: Packet Analysis and Visualization tool

Post by SaveGame »

rocknowx wrote:Duplicate File: RequestRecipeShopMakeItem.xml
Hi,

actually, it isn't a duplicate in this case. The filename was (inadvertently) not updated to match the actual packet name, but that's pretty much it.
You should take note of XML comments in these definition files, they would tell you why those files are kept in this case.

Let me explain the incremental loading for CM_REQ_RECIPE_SHOP_MAKE_DO:
1. Initially, the packet was introduced in C2 (both opcode_mapping.xml and /client/RequestRecipeShopMakeDo.xml):

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<packet id="CM_REQ_RECIPE_SHOP_MAKE_DO" xmlns="http://www.l2emu-unique.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.l2emu-unique.net ../../../schemata/packet.xsd">
	<dword alias="Manufacturer's OID" type="ObjectID" />
	<dword alias="Recipe" type="Recipe" />
</packet>
2. Then, the packet structure has changed in C3 555, where a 'price' dword has been added at the end of the packet, most likely to combat scammers that try to quickly resetup prices in their manufacture after a player opens the UI. That way, the player will not be allowed to request a craft that costs 10m adena, even though his UI shows 10 adena from earlier setup:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<!-- Added manufacturing price DWORD at the end of packet -->
<packet id="CM_REQ_RECIPE_SHOP_MAKE_DO" xmlns="http://www.l2emu-unique.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.l2emu-unique.net ../../../schemata/packet.xsd">
	<dword alias="Manufacturer's OID" type="ObjectID" />
	<dword alias="Recipe" type="Recipe" />

	<!-- NEW -->
	<dword alias="Price" />
</packet>
3. Then, it was updated in GF, as part of an update to allow players to have more than 2 billion stackable items. 'price' DWORD was adjusted to a QWORD:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<!-- Manufacturing price is now a QWORD -->
<packet id="CM_REQ_RECIPE_SHOP_MAKE_DO" xmlns="http://www.l2emu-unique.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.l2emu-unique.net ../../../schemata/packet.xsd">
	<dword alias="Manufacturer's OID" type="ObjectID" />
	<dword alias="Recipe" type="Recipe" />
	<qword alias="Price" /> <!-- NEW -->
</packet>
So, as you can see, all three files serve a clear purpose. That's why they are kept.

Regards,
SaveGame
Image
Post Reply