Jump to content

Recommended Posts

  • Premium

When you are changing attributes in your item for every-single attribute server sends update packet to client, which is up to 4 unnecessary packets per one change. You must agree this is pointless. If you use bonus switcher and, let's say, with 500ms delay for 7 items it is 5 * 7 * 2 update packets per second. Going lower with delay you will get absurd amount of those packets. Another issue is you are not able to read attributes, I mean, avarage human cannot. After digging in code I got rid of redundant packets and received smoother in-game experience

 

Spoiler

item.cpp

 

// search for:


CItem::CItem(DWORD dwVnum)
    : m_dwVnum(dwVnum), m_bWindow(0), m_dwID(0), m_bEquipped(false), m_dwVID(0), m_wCell(0), m_dwCount(0), m_lFlag(0), m_dwLastOwnerPID(0),
    m_bExchanging(false), m_pkDestroyEvent(NULL), m_pkUniqueExpireEvent(NULL), m_pkTimerBasedOnWearExpireEvent(NULL), m_pkRealTimeExpireEvent(NULL),
    m_pkExpireEvent(NULL),
       m_pkAccessorySocketExpireEvent(NULL), m_pkOwnershipEvent(NULL), m_dwOwnershipPID(0), m_bSkipSave(false), m_isLocked(false),
    m_dwMaskVnum(0), m_dwSIGVnum (0)
{
    memset( &m_alSockets, 0, sizeof(m_alSockets) );
    memset( &m_aAttr, 0, sizeof(m_aAttr) );
}

// extend it with ", m_bIsChangingAttr(false)" like shown:


CItem::CItem(DWORD dwVnum)
    : m_dwVnum(dwVnum), m_bWindow(0), m_dwID(0), m_bEquipped(false), m_dwVID(0), m_wCell(0), m_dwCount(0), m_lFlag(0), m_dwLastOwnerPID(0),
    m_bExchanging(false), m_pkDestroyEvent(NULL), m_pkUniqueExpireEvent(NULL), m_pkTimerBasedOnWearExpireEvent(NULL), m_pkRealTimeExpireEvent(NULL),
    m_pkExpireEvent(NULL),
       m_pkAccessorySocketExpireEvent(NULL), m_pkOwnershipEvent(NULL), m_dwOwnershipPID(0), m_bSkipSave(false), m_isLocked(false),
    m_dwMaskVnum(0), m_dwSIGVnum (0), m_bIsChangingAttr(false)
{
    memset( &m_alSockets, 0, sizeof(m_alSockets) );
    memset( &m_aAttr, 0, sizeof(m_aAttr) );
}

// search for:


    m_bSkipSave = false;

// add below:


    m_bIsChangingAttr = false;

// search for:


    if (!m_pOwner || !m_pOwner->GetDesc())
        return;

// add below:


    if (IsChangingAttr())
        return;

item.h

 

// search for:


        DWORD    GetSIGVnum() const
        {
            return m_dwSIGVnum;
        }

// add below:


    public:
        bool        IsChangingAttr() { return m_bIsChangingAttr; }
        void        SetChangingAttr(bool changing) { m_bIsChangingAttr = changing; }
    private:
        bool        m_bIsChangingAttr;

item_attribute.cpp

 

// inside function "ChangeAttribute" search for:


    int iAttributeCount = GetAttributeCount();

// add below:


    SetChangingAttr(true);

// inside function "ChangeAttribute" search for:


    for (int i = GetAttributeCount(); i < iAttributeCount; ++i)
    {
        if (aiChangeProb == NULL)
        {
            PutAttribute(tmpChangeProb);
        }
        else
        {
            PutAttribute(aiChangeProb);
        }
    }

// add below:


    SetChangingAttr(false);
    UpdatePacket();

 

 

This how it looks for 150ms switch delay: gif

With my fix: gif

 

Download: 

This is the hidden content, please

 

Edited by Metin2 Dev
Core X - External 2 Internal
  • Metin2 Dev 79
  • Eyes 1
  • Dislove 1
  • Confused 2
  • Good 12
  • Love 3
  • Love 35
Link to comment
https://metin2.dev/topic/23551-improvement-attribute-changing/
Share on other sites

4 hours ago, filipw1 said:

When you are changing attributes in your item for every-single attribute server sends update packet to client, which is up to 4 unnecessary packets per one change. You must agree this is pointless. If you use bonus switcher and, let's say, with 500ms delay for 7 items it is 5 * 7 * 2 update packets per second. Going lower with delay you will get absurd amount of those packets. Another issue is you are not able to read attributes, I mean, avarage human cannot. After digging in code I got rid of redundant packets and received smoother in-game experience

 

This how it looks for 150ms switch delay: gif

With my fix: gif

 

Download: 

This is the hidden content, please

 


Good Job :)

Mind telling me why you recorded 2 diff. clients?

Edited by Metin2 Dev
Core X - External 2 Internal
  • Metin2 Dev 1
  • Love 1
  • Premium
On 4/25/2020 at 8:03 PM, Leafxc said:


Good Job :)

Mind telling me why you recorded 2 diff. clients?

I have an old server project on my pc, I used it to demonstrate problem, since I don't have this fix there, then I used another server project I'm working on 

  • 1 year later...
  • Honorable Member

I would like to mention here a minor bugfix about the update packets which cause the lags on changing attributes (maybe with manual mouse drag only? dunno).
I hope it is visible on the video, if not just test it by yourself.
 

What you need to do with these microlags is easy, just open the interfaceModule.py and there inside the Interface class you will find a function which is the RefreshInventory.
Every different window which has refreshable item grid, it runs down from there even if the windows isn't opened. This cause the fps drop which is visible even with human eyes.
The solution is, you have to put an (IsShow) if statement before they run down like the way how it looks like on my side:

	def RefreshInventory(self):
		self.wndTaskBar.RefreshQuickSlot()
		if self.wndInventory and self.wndInventory.IsShow():
			self.wndInventory.RefreshItemSlot()
		if app.ENABLE_DRAGON_SOUL_SYSTEM:
			if self.wndDragonSoul and self.wndDragonSoul.IsShow():
				self.wndDragonSoul.RefreshItemSlot()
		if app.ENABLE_EXTEND_INVEN_SYSTEM and app.ENABLE_SEPARATED_EXTEND_INVEN_WINDOW:
			if self.wndInventoryEx and self.wndInventoryEx.IsShow():
				self.wndInventoryEx.RefreshItemSlot()
		if app.ENABLE_MOVE_COSTUME_ATTR or app.ENABLE_MOVE_SASH_ATTR:
			if app.GetMoveAttrWindowOpen():
				if self.wndItemCombination and self.wndItemCombination.IsShow():
					self.wndItemCombination.RefreshCombSlotWindow()
		if app.ENABLE_SHOULDER_SASH_SYSTEM:
			if player.GetAcceRefineWindowOpen():
				if self.wndAcce and self.wndAcce.IsShow():
					self.wndAcce.RefreshAcceWindow()
		if app.ENABLE_CHANGE_LOOK_SYSTEM:
			if player.GetChangeLookWindowOpen():
				if self.wndChangeLook and self.wndChangeLook.IsShow():
					self.wndChangeLook.RefreshChangeLookWindow()
		if self.wndAttr67Add and self.wndAttr67Add.IsShow():
			self.wndAttr67Add.RefreshAttr67Window()
		if app.ENABLE_AURA_SYSTEM:
			if player.IsAuraRefineWindowOpen():
				if self.wndAura and self.wndAura.IsShow():
					self.wndAura.RefreshAuraWindow()
Edited by Metin2 Dev
Core X - External 2 Internal
  • Metin2 Dev 46
  • Dislove 1
  • Angry 1
  • Scream 1
  • Good 13
  • Love 1
  • Love 7
  • 1 month later...

In CPythonNetworkStream::RecvItemUpdatePacket() we got 2x `RefreshInventory` function' callback.
First in

rkPlayer.SetItemCount(packet_item_update.Cell, packet_item_update.count);

Second is in before `return true;`
You can comment `RefreshInventory` callback in SetItemCount but you have to remember about dss refine window. After remove that line, stones will not update themselves.

  • 1 year later...
On 10/22/2021 at 2:16 PM, xP3NG3Rx said:

I would like to mention here a minor bugfix about the update packets which cause the lags on changing attributes (maybe with manual mouse drag only? dunno).
I hope it is visible on the video, if not just test it by yourself.
 

What you need to do with these microlags is easy, just open the interfaceModule.py and there inside the Interface class you will find a function which is the RefreshInventory.
Every different window which has refreshable item grid, it runs down from there even if the windows isn't opened. This cause the fps drop which is visible even with human eyes.
The solution is, you have to put an (IsShow) if statement before they run down like the way how it looks like on my side:

	def RefreshInventory(self):
		self.wndTaskBar.RefreshQuickSlot()
		if self.wndInventory and self.wndInventory.IsShow():
			self.wndInventory.RefreshItemSlot()
		if app.ENABLE_DRAGON_SOUL_SYSTEM:
			if self.wndDragonSoul and self.wndDragonSoul.IsShow():
				self.wndDragonSoul.RefreshItemSlot()
		if app.ENABLE_EXTEND_INVEN_SYSTEM and app.ENABLE_SEPARATED_EXTEND_INVEN_WINDOW:
			if self.wndInventoryEx and self.wndInventoryEx.IsShow():
				self.wndInventoryEx.RefreshItemSlot()
		if app.ENABLE_MOVE_COSTUME_ATTR or app.ENABLE_MOVE_SASH_ATTR:
			if app.GetMoveAttrWindowOpen():
				if self.wndItemCombination and self.wndItemCombination.IsShow():
					self.wndItemCombination.RefreshCombSlotWindow()
		if app.ENABLE_SHOULDER_SASH_SYSTEM:
			if player.GetAcceRefineWindowOpen():
				if self.wndAcce and self.wndAcce.IsShow():
					self.wndAcce.RefreshAcceWindow()
		if app.ENABLE_CHANGE_LOOK_SYSTEM:
			if player.GetChangeLookWindowOpen():
				if self.wndChangeLook and self.wndChangeLook.IsShow():
					self.wndChangeLook.RefreshChangeLookWindow()
		if self.wndAttr67Add and self.wndAttr67Add.IsShow():
			self.wndAttr67Add.RefreshAttr67Window()
		if app.ENABLE_AURA_SYSTEM:
			if player.IsAuraRefineWindowOpen():
				if self.wndAura and self.wndAura.IsShow():
					self.wndAura.RefreshAuraWindow()

I think that your solution is not exactly the best and look why I say this.

https://metin2.download/video/1vvoUjT5M4F92GSSJrpAB3tu6vtUd3iM/.mp4

Edited by Metin2 Dev International
Core X - External 2 Internal
  • Good 1

Don't use any images from : imgur, turkmmop, freakgamers, inforge, hizliresim... Or your content will be deleted without notice...
Use : https://metin2.download/media/add/

Please use https://metin2.download/ when uploading files smaller than 100MB, otherwise the approval will take longer due to manual upload.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.