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):
hp/mpPotionTypes are global arrays:
3 examples of the behaviours:
A working one:
And a bugged one:
Note: the potion in slot 7 was not drunk, I had to nexus.
The extreme case:
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.
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)
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))
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
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
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"
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.

objectId=251726 slotId=5 objectType=2594] itemUsePos