HelpAuto-potter failure in proxy

Posts 1–12 of 12 · Page 1 of 1
Auto-potter failure in proxy
I'm making an auto-potter, for my clients, bots and proxy, but I encountered a strange bug: drinking potions fails sometimes. In one of the realms it works properly 10/10, in other realms it randomly fails (1/10), and if it fails too many times, I get disconnected. Probably realms are unreleated, but then i don't know what could trigger this random behaviour, so if any of you knows about server-sided restrictions of USEITEM packet, please share it.

In any case here is the code, it is called uppon receiving a NEW_TICK packet (tried in MOVE packet as well for better time and position precision):
Code:
def autoPotter(conn):
	player = conn.gameObjects[conn.myObjectId]
	condition = player.stats[StatData.CONDITION]
	hp = player.stats[StatData.HEALTH]
	maxhp = player.stats[StatData.MAX_HEALTH]
	mp = player.stats[StatData.MANA]
	maxmp = player.stats[StatData.MAX_MANA]
	
	if hp / maxhp < float(config['Game']['hpPotting']) and conn.mapinfo.name != 'Nexus' \
	and not (condition & (ConditionEffects.SICK | ConditionEffects.PAUSED)):
		pkt = packet.USEITEM()
		pkt.time = conn.gameTime
		pkt.slotObject = SlotObject()
		pkt.slotObject.objectId = conn.myObjectId
		for playerSlot in range(4, 12):
			if player.stats[StatData.INVENTORY[playerSlot]] in hpPotionTypes:
				pkt.slotObject.slotId = playerSlot
				pkt.slotObject.objectType = player.stats[StatData.INVENTORY[playerSlot]]
				pkt.itemUsePos = Position()
				break
		else:
			pkt.slotObject.slotId = 254
			pkt.slotObject.objectType = hpPotionTypes[0]
			pkt.itemUsePos = conn.myPosition
		pkt.useType = 1
		pkt.loaded = True
		if not checkIfCostsGold(conn, pkt):
			conn.sendPacket(pkt.getType(), pkt.getData(), conn.c2s)
			print(pkt)
			
	elif mp / maxmp < float(config['Game']['mpPotting']) and conn.mapinfo.name != 'Nexus' \
	and not (condition & (ConditionEffects.QUIET | ConditionEffects.PAUSED)):
		pkt = packet.USEITEM()
		pkt.time = conn.gameTime
		pkt.slotObject = SlotObject()
		pkt.slotObject.objectId = conn.myObjectId
		for playerSlot in range(4, 12):
			if player.stats[StatData.INVENTORY[playerSlot]] in mpPotionTypes:
				pkt.slotObject.slotId = playerSlot
				pkt.slotObject.objectType = player.stats[StatData.INVENTORY[playerSlot]]
				pkt.itemUsePos = Position()
				break
		else:
			pkt.slotObject.slotId = 255
			pkt.slotObject.objectType = mpPotionTypes[0]
			pkt.itemUsePos = conn.myPosition
		pkt.useType = 1
		pkt.loaded = True
		if not checkIfCostsGold(conn, pkt):
			conn.sendPacket(pkt.getType(), pkt.getData(), conn.c2s)
			print(pkt)
hp/mpPotionTypes are global arrays:
Code:
	xmlRoots = {os.path.splitext(os.path.basename(file))[0]:ElementTree.parse(file).getroot() for file in glob.glob('xml/*.xml')}
	
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Health Potion']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Minor Health Potion']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Fire Water']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Chardonnay']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Cabernet']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Sauvignon Blanc']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Rice Wine']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Health 7']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Health 6']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Health 5']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Health 4']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Health 3']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Health 2']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Health 1']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Healing Ichor']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Greater Health Potion']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Coral Juice']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Holy Water']").get('type'), 0))
	hpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Snake Oil']").get('type'), 0))
	
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Magic Potion']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Minor Magic Potion']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Cream Spirit']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Melon Liqueur']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Vintage Port']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Muscat']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Shiraz']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Magic 7']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Magic 6']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Magic 5']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Magic 4']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Magic 3']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Magic 2']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Elixir of Magic 1']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Greater Magic Potion']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Coral Juice']").get('type'), 0))
	mpPotionTypes.append(int(xmlRoots['Equip'].find("./Object[@id='Pollen Powder']").get('type'), 0))
3 examples of the behaviours:
A working one:
Code:
USEITEM: time=3995422 slotObject=[objectId=234029 slotId=5 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=3996231 slotObject=[objectId=234029 slotId=6 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=3996420 slotObject=[objectId=234029 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=3998046 slotObject=[objectId=234029 slotId=9 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=3998451 slotObject=[objectId=234029 slotId=10 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=4004904 slotObject=[objectId=234029 slotId=11 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
And a bugged one:
Code:
USEITEM: time=9734422 slotObject=[objectId=251726 slotId=5 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9734610 slotObject=[objectId=251726 slotId=5 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9734814 slotObject=[objectId=251726 slotId=5 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9734994 slotObject=[objectId=251726 slotId=5 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9735216 slotObject=[objectId=251726 slotId=5 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9735428 slotObject=[objectId=251726 slotId=6 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9760197 slotObject=[objectId=251726 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9760396 slotObject=[objectId=251726 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9760616 slotObject=[objectId=251726 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9760786 slotObject=[objectId=251726 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9760993 slotObject=[objectId=251726 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9761193 slotObject=[objectId=251726 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=9761365 slotObject=[objectId=251726 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
Note: the potion in slot 7 was not drunk, I had to nexus.
The extreme case:
Code:
USEITEM: time=6969045 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6969251 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6969421 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6969622 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6969827 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6970019 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6973643 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6973845 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6974054 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6976050 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6976244 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6976457 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6976674 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6976855 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6977051 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6977293 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6977474 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6977690 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6977878 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6978071 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6978269 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6978475 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6978653 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6978899 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6979057 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
USEITEM: time=6979668 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
FAILURE: errorId=0 errorDescription="Lost connection to server"
Note: it seems if I manually drink a potion from the inv, the client sends [0;0] itemUsePos, otherwise it sends the player position, so I do the same, but first I tried always sending the player postion, it seems it doesn't matter. Too short time gaps doesn't seem to be a problem like in the case of INVSWAP.

It's not a big issue, but I'd like to solve it, so if anyone finds a mistake or know more about the topic, please share it. I will try waiting for a server response and implement a timeout so it doesn't spam it after every NEW_TICK if failed, maybe the server is just too slow but I don't think that's the issue, because in the last example, there are cases where it waits 3-4 seconds and no response nevertheless.
for playerSlot in range(4, 12): this might be a cause but i don't know
1 2 3 4 are for equipment

edit (1)
0 index, 0123 = equipments, you have added some management to the raw statdata, to make accessing the inventory easier.

edit (2)
@DatCoder
Is it possible that after sending the use item packet, the stat data remains the same for the next tick update, I can’t see you resetting the slot to empty, because of lag the stat data could be wrong and your sending another use item packet for a empty slot.
Well I assumed that disconnections like this were due to spamming a packet too many times. I know auto-nexus kicks to character selection screen at times for this very reason. Maybe increase the useitem request to something > 200ms?
Quote Originally Posted by Botmaker View Post
for playerSlot in range(4, 12): this might be a cause but i don't know
1 2 3 4 are for equipment

edit
0 index, 0123 = equipments, you have added some management to the raw statdata, to make accessing the inventory easier.
That line in C/Java:
Code:
for(playerSlot=4; playerSlot < 12; playerSlot++)
so it's [4..11] and has nothing to do with items. The code works the item id and slot is fine, I can assure you that the object id is the player's id. The statdata is good as it is, because in other objects the inventory is [0..7].

Quote Originally Posted by nilly View Post
Well I assumed that disconnections like this were due to spamming a packet too many times. I know auto-nexus kicks to character selection screen at times for this very reason. Maybe increase the useitem request to something > 200ms?
I know that, but the real question is why the server doesn't react to the packet sometimes? It's totally random:
Code:
USEITEM: time=6970019 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
*nothing happens... let's wait... 3.6 sec later:*
USEITEM: time=6973643 slotObject=[objectId=3036 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
*nothing happens...*
but
Code:
USEITEM: time=3996231 slotObject=[objectId=234029 slotId=6 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
*drinks potion... 190ms later:*
USEITEM: time=3996420 slotObject=[objectId=234029 slotId=7 objectType=2594] itemUsePos=[x=0.0 y=0.0] useType=1
*drinks potion...*
A lot of failures cause disconnection, but why does it fail randomly in the first place?
i know it takes some time for me to get use to your code, i work with the raw statdata 8 to 19.

@DatCoder
Is it possible that after sending the use item packet, the stat data remains the same for the next tick update, I can’t see you resetting the slot to empty, because of lag the stat data could be wrong and your sending another use item packet for a empty slot.
Quote Originally Posted by Botmaker View Post
@DatCoder
Is it possible that after sending the use item packet, the stat data remains the same for the next tick update, I can’t see you resetting the slot to empty, because of lag the stat data could be wrong and your sending another use item packet for a empty slot.
I used to reset it but the next NEW_TICK writes it back anyway if it fails, and if it doesn't then it will be reseted. In the case of lag I would need a timer, but it fail anyway, whenever I wait or resend it. You could see the example, there are cases when I wait and still fails and vice versa.
Even the first packet fails with an untouched statdata, so that's not the issue for sure.

---------- Post added at 05:37 AM ---------- Previous post was at 05:32 AM ----------

Quote Originally Posted by Botmaker View Post
i know it takes some time for me to get use to your code, i work with the raw statdata 8 to 19.
I posted a complete list of statdata in the relevant information thread, you should use it.
@DatCoder
ok one last thing is, maybe you send two use item packets, one for the hp and one for the mp at the same time.
Quote Originally Posted by Botmaker View Post
@DatCoder
ok one last thing is, maybe you send two use item packets, one for the hp and one for the mp at the same time.
That wouldn't be an issue, but it's impossible since I used elif for mp (elif is else if for short). The reason I did because the coral juice can be used in both cases so I didn't want conflict.
@DatCoder
I’m tired so please forgive me for being a hindrance, shouldn’t there be only one use item packet for each slot? slot id 5 is sent 5 times in less then a second

USEITEM: time=9734422 slotObjectobjectId=251726 slotId=5 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9734610 slotObjectobjectId=251726 slotId=5 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9734814 slotObjectobjectId=251726 slotId=5 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9734994 slotObjectobjectId=251726 slotId=5 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9735216 slotObjectobjectId=251726 slotId=5 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9735428 slotObjectobjectId=251726 slotId=6 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9760197 slotObjectobjectId=251726 slotId=7 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9760396 slotObjectobjectId=251726 slotId=7 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9760616 slotObjectobjectId=251726 slotId=7 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9760786 slotObjectobjectId=251726 slotId=7 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9760993 slotObjectobjectId=251726 slotId=7 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9761193 slotObjectobjectId=251726 slotId=7 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
USEITEM: time=9761365 slotObjectobjectId=251726 slotId=7 objectType=2594] itemUsePosx=0.0 y=0.0] useType=1
Quote Originally Posted by Botmaker View Post
@DatCoder
I’m tired so please forgive me for being a hindrance, shouldn’t there be only one use item packet for each slot? slot id 5 is sent 5 times in less then a second
If the potion is not consumet, it retries every 200ms, until is consumed.
@eth0nic: it happens too often to be server-sided problem so I don't think it's off-by-1 bug. I thought about a thread-safety problem, but I don't think that's the case either. I will look into it later, now it's not my first priority.
It's not minimumDelay problem, because at least the first potion would be consumed then.

---------- Post added at 03:41 PM ---------- Previous post was at 03:30 PM ----------

Not it's not thread-safety issue, that's would be impossible by design.
Is there some minimumDelay between consuming potions? Could there be some internal packet loss (_NOT_ network packets) due to some scheduling or off-by-1 bug? I think I have experienced the same thing a few times ... like the client would consume it but health wouldn't change, etc. ... i never used USE_ITEM with my proxy because I am not interested in cheating but I will test next week if the problem persists.

---------- Post added at 11:21 PM ---------- Previous post was at 11:17 PM ----------

Quote Originally Posted by DatCoder View Post
I know that, but the real question is why the server doesn't react to the packet sometimes? It's totally random:
I got the same issue with my trading bots. 2-3 times every hour a packet wouldn't register with the server and the bot will not offer anything and you would need to re-initiate the trade. But given the number of bots that I am using it shouldn't happen that often for any given character/bot ...

---------- Post added at 11:23 PM ---------- Previous post was at 11:21 PM ----------

It really could be a off-by-1 bug ... there could be a packet-queue on their servers for packets that are not really real-time-critical (i.e. the asynchronous ones) ... like chat, trade, use_item ... maybe the iterator just goes up to 999 and will ignore packet #1000 and whoever this packet is from/for will have bad luck?
@DatCoder
The flash client only ever sends one use item packet per inventory slot, also I’m looking into this issue further with a proxy.
Posts 1–12 of 12 · Page 1 of 1

Post a Reply

Similar Threads

Tags for this Thread

None

Talk with us