L2JMobius

High Five Introducing Ghost Services

mastermind007 · 35 · 1288

Online mastermind007

  • Heir
  • **
    • Posts: 20
Hello All,

At Mobius request I convert the Ghost Services into a standalone module.
You can access it here https://gitlab.com/Mastermind007/l2jmobius-ghost-services.git

The readme file has all the detail but the short version is add the GhostServices folder to your servers "data/scripts/custom".
Go to the config folder and enable the shops, manufacture and wanderers (change from False to True).
Start your server as normal.

Now that this module is not coded in the care it should be easier to test with other chronicles.
 

--Mastermind007

EDIT: Here is a video showing the mod in use. This is spawning 200 shops between Giran and Dion. The characters you see running around are the Ghost Wanderers that will buy from real player shops only, if the price is right.

https://youtu.be/v-Uf8ErwQz4
If it ain't broke, you're not trying hard enough.


Online GuruGel

  • Knight
  • ***
    • Posts: 91
I'm having trouble adding high-value items. I get an error about the format being incorrect. How can I fix this?


Online mastermind007

  • Heir
  • **
    • Posts: 20
I'm having trouble adding high-value items. I get an error about the format being incorrect. How can I fix this?

Not sure how you are adding items but I am guessing it is using the shopitems.xml file. Make sure to follow the layout of an existing item in the same category exaactly.

Code: [Select]
<item id="299" name="Orcish Poleaxe" category="Weapon"><MinCount val="1" /><MaxCount val="1" /><BuyLow val="2800000" /><BuyHigh val="3500000" /><SellLow val="3800000" /><SellHigh val="5000000" /><Level val="1" /></item>   
Make sure the category matches exactly as they are used in the code.
Make sure the counts (min/max), as well as the Buy/Sell low and high also have a value. They are quoted in the XML but need to be numbers.
Lastly the Level is a number assigned to the item grade. 1 through 5 equals D through S grade.  This is used to limit the type of items available in Dion only. Every item as a grade associated, even craft mats. Dion gets 1 and 2 (D and C grade) only. Giran has no restriction

It you share exactly what you are wanting to add and what you have so far, I am sure we can get it figured out.

EDIT: This will make life a little easier. This link is for a MySQL dump of the current shopitems table used to create the XML items.  https://pastebin.com/kQf0PPdr

Add your new items to the table using your favorite MySQL tool. You can also update prices on existing items to fit your server
When finished the following query will output the items in the correct XML format. If you only want to create one or two just add a where clause to the query so it only outputs those items. All that is left is to paste then in the XML file and reload the server.

Code: [Select]
SELECT
    CONCAT(
        '<item id="', id, '" name="', NAME, '" category="', category, '">',
        '<MinCount val="', MinCount, '" />',
        '<MaxCount val="', MaxCount, '" />',
        '<BuyLow val="', BuyLow, '" />',
        '<BuyHigh val="', BuyHigh, '" />',
        '<SellLow val="', SellLow, '" />',
        '<SellHigh val="', SellHigh, '" />',
        '<Level val="', LEVEL, '" />',
        '</item>'
    ) AS xml_row
FROM shopitems;
If it ain't broke, you're not trying hard enough.


Online GuruGel

  • Knight
  • ***
    • Posts: 91
Not sure how you are adding items but I am guessing it is using the shopitems.xml file. Make sure to follow the layout of an existing item in the same category exaactly.

Code: [Select]
<item id="299" name="Orcish Poleaxe" category="Weapon"><MinCount val="1" /><MaxCount val="1" /><BuyLow val="2800000" /><BuyHigh val="3500000" /><SellLow val="3800000" /><SellHigh val="5000000" /><Level val="1" /></item>   
Make sure the category matches exactly as they are used in the code.
Make sure the counts (min/max), as well as the Buy/Sell low and high also have a value. They are quoted in the XML but need to be numbers.
Lastly the Level is a number assigned to the item grade. 1 through 5 equals D through S grade.  This is used to limit the type of items available in Dion only. Every item as a grade associated, even craft mats. Dion gets 1 and 2 (D and C grade) only. Giran has no restriction

It you share exactly what you are wanting to add and what you have so far, I am sure we can get it figured out.

EDIT: This will make life a little easier. This link is for a MySQL dump of the current shopitems table used to create the XML items.  https://pastebin.com/kQf0PPdr

Add your new items to the table using your favorite MySQL tool. You can also update prices on existing items to fit your server
When finished the following query will output the items in the correct XML format. If you only want to create one or two just add a where clause to the query so it only outputs those items. All that is left is to paste then in the XML file and reload the server.

Code: [Select]
SELECT
    CONCAT(
        '<item id="', id, '" name="', NAME, '" category="', category, '">',
        '<MinCount val="', MinCount, '" />',
        '<MaxCount val="', MaxCount, '" />',
        '<BuyLow val="', BuyLow, '" />',
        '<BuyHigh val="', BuyHigh, '" />',
        '<SellLow val="', SellLow, '" />',
        '<SellHigh val="', SellHigh, '" />',
        '<Level val="', LEVEL, '" />',
        '</item>'
    ) AS xml_row
FROM shopitems;
this value gives an error:
Code: [Select]
<BuyLow val="6062212500" /><BuyHigh val="7062212500" /><SellLow val="6062212500" /><SellHigh val="7062212500" />Writes this error:
Code: [Select]
[main] ERROR org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData - GhostShopItemData: Error loading Shop XML:
java.lang.NumberFormatException: For input string: "6062212500"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:527)
at java.base/java.lang.Integer.parseInt(Integer.java:624)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData.parseItem(GhostShopItemData.java:80)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData.load(GhostShopItemData.java:50)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData.<init>(GhostShopItemData.java:31)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData$SingletonHolder.<clinit>(GhostShopItemData.java:125)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData.getInstance(GhostShopItemData.java:102)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopManager.applyItemsToOfflineShop(GhostShopManager.java:331)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopManager.createOfflineGhostShop(GhostShopManager.java:189)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopManager.createGhostShopRandom(GhostShopManager.java:140)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopManager.startBatchSpawning(GhostShopManager.java:589)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopManager.initStartupSpawns(GhostShopManager.java:570)
at org.l2jmobius.gameserver.GameServer.<init>(GameServer.java:510)
at org.l2jmobius.gameserver.GameServer.main(GameServer.java:601)


Online mastermind007

  • Heir
  • **
    • Posts: 20
this value gives an error:
Code: [Select]
<BuyLow val="6062212500" /><BuyHigh val="7062212500" /><SellLow val="6062212500" /><SellHigh val="7062212500" />Writes this error:
Code: [Select]
[main] ERROR org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData - GhostShopItemData: Error loading Shop XML:
java.lang.NumberFormatException: For input string: "6062212500"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:527)
at java.base/java.lang.Integer.parseInt(Integer.java:624)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData.parseItem(GhostShopItemData.java:80)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData.load(GhostShopItemData.java:50)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData.<init>(GhostShopItemData.java:31)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData$SingletonHolder.<clinit>(GhostShopItemData.java:125)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopItemData.getInstance(GhostShopItemData.java:102)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopManager.applyItemsToOfflineShop(GhostShopManager.java:331)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopManager.createOfflineGhostShop(GhostShopManager.java:189)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopManager.createGhostShopRandom(GhostShopManager.java:140)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopManager.startBatchSpawning(GhostShopManager.java:589)
at org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopManager.initStartupSpawns(GhostShopManager.java:570)
at org.l2jmobius.gameserver.GameServer.<init>(GameServer.java:510)
at org.l2jmobius.gameserver.GameServer.main(GameServer.java:601)

That price is way higher than expected. 6 billion adena? Is that correct or a typo?
The cause it the parser uses a standard integer which in java has a max value of  2,147,483,647

To allow for such high values the code would need changed in both GhostShopItem.java and GhostShopItemData.java, changing int to long for the buy and sell low/high. I am not in a position to do that now but maybe tomorrow I can take a look.
If it ain't broke, you're not trying hard enough.


Online BazookaRpm

  • Count
  • *****
    • Posts: 443
  • Lineage II - lover - Heirophant
It's a good contribution; it would be good to adapt them to all projects.
Atte BazooKa.RPM

Lineage II Lovers


Online GuruGel

  • Knight
  • ***
    • Posts: 91
That price is way higher than expected. 6 billion adena? Is that correct or a typo?
The cause it the parser uses a standard integer which in java has a max value of  2,147,483,647

To allow for such high values the code would need changed in both GhostShopItem.java and GhostShopItemData.java, changing int to long for the buy and sell low/high. I am not in a position to do that now but maybe tomorrow I can take a look.


Yes, that's exactly the value. I implemented this mod into the Wolf Vagr Chronicles. And that's the price of the items there.


Online GuruGel

  • Knight
  • ***
    • Posts: 91
That price is way higher than expected. 6 billion adena? Is that correct or a typo?
The cause it the parser uses a standard integer which in java has a max value of  2,147,483,647

To allow for such high values the code would need changed in both GhostShopItem.java and GhostShopItemData.java, changing int to long for the buy and sell low/high. I am not in a position to do that now but maybe tomorrow I can take a look.

and I changed int to long in this file, but nothing changed, the error is still there.


Online mastermind007

  • Heir
  • **
    • Posts: 20
and I changed int to long in this file, but nothing changed, the error is still there.

There are multiple places the int needed changed to long.
I made the change and push a commit to the repo mention in my initial post.

Did adding this mod to Wolf Vagr give you any issues, other than the price value?
Was hoping the code for newer chronicles did not change much so it would be usable with them.
If it ain't broke, you're not trying hard enough.


Online GuruGel

  • Knight
  • ***
    • Posts: 91
There are multiple places the int needed changed to long.
I made the change and push a commit to the repo mention in my initial post.

Did adding this mod to Wolf Vagr give you any issues, other than the price value?
Was hoping the code for newer chronicles did not change much so it would be usable with them.

The only problem was the price.


Online GuruGel

  • Knight
  • ***
    • Posts: 91
There's an issue with replacing merchants and ghost buyers. When it comes time to replace existing merchants and buyers, the system doesn't replace them, but simply adds new ones. What's responsible for removing ghost merchants and buyers from the game and replacing them with new ones?


Online mastermind007

  • Heir
  • **
    • Posts: 20
There's an issue with replacing merchants and ghost buyers. When it comes time to replace existing merchants and buyers, the system doesn't replace them, but simply adds new ones. What's responsible for removing ghost merchants and buyers from the game and replacing them with new ones?

Shops:
Towards the end of the "createOfflineGhostShop" there is the line             
Code: [Select]
schedulePurge(ghost.getObjectId(), name, Rnd.get(ROTATION_MIN_HOURS, ROTATION_MAX_HOURS) * ROTATION_MAX_HOURS_MULTIPLIER);
The "schedulePurge" creates that actual timer for the shop to remove the it and start a replacement shop.
You should soo the message in the server log when this fires
Code: [Select]
LOG.info("Rotated out {} (ID: {})", name, objectId);
Buyers:
They follow a similar approach but beings there are far fewer of then that shops they rotate out as a group. The "scheduleNextRotation()" establishes the schedule based on the min/max hours set in the config file. When the event fires all are replaced with new ones.
When this fires you should see a server log message
Code: [Select]
LOG.info("Batch rotated successfully.");
I guess to start are you seeing any of this messages in the log?
If it ain't broke, you're not trying hard enough.


Online GuruGel

  • Knight
  • ***
    • Posts: 91
Shops:
Towards the end of the "createOfflineGhostShop" there is the line             
Code: [Select]
schedulePurge(ghost.getObjectId(), name, Rnd.get(ROTATION_MIN_HOURS, ROTATION_MAX_HOURS) * ROTATION_MAX_HOURS_MULTIPLIER);
The "schedulePurge" creates that actual timer for the shop to remove the it and start a replacement shop.
You should soo the message in the server log when this fires
Code: [Select]
LOG.info("Rotated out {} (ID: {})", name, objectId);
Buyers:
They follow a similar approach but beings there are far fewer of then that shops they rotate out as a group. The "scheduleNextRotation()" establishes the schedule based on the min/max hours set in the config file. When the event fires all are replaced with new ones.
When this fires you should see a server log message
Code: [Select]
LOG.info("Batch rotated successfully.");
I guess to start are you seeing any of this messages in the log?

Yes, the server console says everything went well, but in fact it added new ones and didn't delete the old ones.


Online GuruGel

  • Knight
  • ***
    • Posts: 91
Code: [Select]
:07] New maximum connected count of 643!
[L2jMobius ScheduledThread 48] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopGiranManager - Rotated out Ithenlan (ID: 268513085)
[17/04 19:55:09] New maximum connected count of 644!
[L2jMobius ScheduledThread 43] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopRunaManager - Rotated out Елонбане (ID: 268515633)
[L2jMobius ScheduledThread 9] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopGiranManager - Rotated out Faerentide (ID: 268511695)
[17/04 19:55:12] New maximum connected count of 645!
[L2jMobius ScheduledThread 53] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopRunaManager - Rotated out Силиус (ID: 268512434)
[17/04 19:55:14] New maximum connected count of 647!
[L2jMobius ScheduledThread 75] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopGiranManager - Rotated out Zansong (ID: 268515750)
[L2jMobius ScheduledThread 40] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopRunaManager - Rotated out Валбане (ID: 268512855)
[L2jMobius ScheduledThread 49] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopGiranManager - Rotated out Ithius (ID: 268515995)
[17/04 19:55:21] New maximum connected count of 648!
[L2jMobius ScheduledThread 76] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopRunaManager - Rotated out Кинтхас (ID: 268512553)
[L2jMobius ScheduledThread 6] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopRunaManager - Rotated out Оникстхас (ID: 268510859)
[17/04 19:55:24] New maximum connected count of 650!
[L2jMobius ScheduledThread 39] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopGiranManager - Rotated out Syldar (ID: 268516175)
[L2jMobius ScheduledThread 2] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopGiranManager - Rotated out Bravorwyn (ID: 268510236)
[L2jMobius ScheduledThread 11] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopGiranManager - Rotated out Azislith (ID: 268513410)
[L2jMobius ScheduledThread 77] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopRunaManager - Rotated out Рхуниррим (ID: 268511449)
[L2jMobius ScheduledThread 36] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopGiranManager - Rotated out Cynmorn (ID: 268513404)
[L2jMobius ScheduledThread 14] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopGiranManager - Rotated out Indarvane (ID: 268513134)
[17/04 19:55:28] New maximum connected count of 651!
[L2jMobius ScheduledThread 58] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopGiranManager - Rotated out Faeronbore (ID: 268511972)
[L2jMobius ScheduledThread 49] INFO org.l2jmobius.gameserver.ghostservices.ghostshops.GhostShopRunaManager - Rotated out Ваелумиус (ID: 268515751)
[17/04 19:55:33] New maximum connected count of 653!
[17/04 19:55:36] New maximum connected count of 654!
[17/04 19:55:37] New maximum connected count of 655!
[17/04 19:55:39] New maximum connected count of 656!


This is what the console says and continues to increase the maximum online...


Online GuruGel

  • Knight
  • ***
    • Posts: 91
And the most interesting thing is, the database only lists 150 ghost shops and 30 runners. But in fact, there are already over 1,000 of them in the game... and the number is growing.