Skip to content
This repository has been archived by the owner on Jan 28, 2022. It is now read-only.

setFavoritePokemon pokemon_id data type #188

Closed
earshel opened this issue Aug 13, 2016 · 11 comments
Closed

setFavoritePokemon pokemon_id data type #188

earshel opened this issue Aug 13, 2016 · 11 comments

Comments

@earshel
Copy link

earshel commented Aug 13, 2016

Thank you for all of your continued work on these Protos. My project wouldn't be possible without them :). I've got a minor issue with one of the Protos, outlined below.

The data type is currently set as INT64 and this can cause an out of range exception if the following condition is true:

pokemon_id > 9223372036854775807

This has happened to me on a few occasions. An example of this:

File "C:\Python27\lib\site-packages\google\protobuf\internal\type_checkers.py", line 134, in CheckValue
if not isinstance(proposed_value, six.integer_types):
message = ('%.1024r has type %s, but expected one of: %s' %
(proposed_value, type(proposed_value), six.integer_types))
raise TypeError(message)
if not self._MIN <= proposed_value <= self._MAX:
raise ValueError('Value out of range: %d' % proposed_value)
# We force 32-bit values to int and 64-bit values to long to make
# alternate implementations where the distinction is more significant
# (e.g. the C++ implementation) simpler.
proposed_value = self._TYPE(proposed_value)
return proposed_value
ValueError: Value out of range: 9616888052755598152

We force 32-bit values to int and 64-bit values to long to make
# alternate implementations where the distinction is more significant
# (e.g. the C++ implementation) simpler.
proposed_value = self._TYPE(proposed_value)
return proposed_value
ValueError: Value out of range: 9616888052755598152

See Python data types here for verification:
http://docs.scipy.org/doc/numpy-1.10.1/user/basics.types.html

Changing pokemon_id's type to UINT64 solves this problem as the upper limit of the range is 18446744073709551615.

@seikur0
Copy link

seikur0 commented Aug 13, 2016

Which protos file are you talking about? I have pokemon_id values between 1 and 151? xD

@earshel
Copy link
Author

earshel commented Aug 13, 2016

Networking/Requests/SetFavoritePokemonMessage_pb2 line 37 - it's not referring to the Pokemon's Pokedex ID. Each of your Pokemon have a unique ID associated with them. It's visible in session.getInventory:

   #id: 2436312686824190668
    #pokemon_id: EEVEE
    #cp: 46
    #stamina: 19
    #stamina_max: 19
    #move_1: TACKLE_FAST
    #move_2: DIG
    #height_m: 0.297532558441
    #weight_kg: 8.24643802643
    #individual_attack: 15
    #individual_defense: 12
    #individual_stamina: 9
    #cp_multiplier: 0.166397869587
    #pokeball: ITEM_POKE_BALL
    #captured_cell_id: 6108423709528162304
    #creation_time_ms: 1469364470778

@seikur0
Copy link

seikur0 commented Aug 13, 2016

I see, in that case you're probably right. Until they change it you can change it yourself and recompile or use something like pokemon_id = ctypes.c_longlong(pokemon_id)

@earshel
Copy link
Author

earshel commented Aug 13, 2016

Changing the type and cpp_type to 4 in this section actually solves the issue for me:

 fields=[
    _descriptor.FieldDescriptor(
      name='pokemon_id', full_name='POGOProtos.Networking.Requests.Messages.SetFavoritePokemonMessage.pokemon_id', index=0,
      number=1, type=4, cpp_type=4, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),

@Grover-c13
Copy link
Contributor

Grover-c13 commented Aug 17, 2016

according to current dumps the game is still usings longs for pokemon ids,

public sealed class SetFavoritePokemonProto // TypeDefinitionIndex: 4645
{
// Fields
public static int PokemonIdFieldNumber = 1;
public static int IsFavoriteFieldNumber = 2;
private static MessageParser1<SetFavoritePokemonProto> _parser; private long pokemonId_; private bool isFavorite_; private static Func1 <>f__am$cache3;
// Methods
public void .ctor(); // 360834
public void .ctor(SetFavoritePokemonProto other); // 3608b8
private static void .cctor(); // 360bc4
private virtual MessageDescriptor Google.Protobuf.IMessage.get_Descriptor(); // 3610a0
public static MessageParser`1 get_Parser(); // 36176c
public static MessageDescriptor get_Descriptor(); // 361b94
public virtual SetFavoritePokemonProto Clone(); // 361ca0
public long get_PokemonId(); // 361f24
public void set_PokemonId(long value); // 362498
public bool get_IsFavorite(); // 362578
public void set_IsFavorite(bool value); // 362a34
public virtual bool Equals(mvar other); // 361de0
public virtual bool Equals(SetFavoritePokemonProto other); // 362ed4
public virtual int GetHashCode(); // 36088c
public virtual String ToString(); // 360e2c
public virtual void WriteTo(CodedOutputStream output); // 36236c
public virtual int CalculateSize(); // 362f30
public virtual void MergeFrom(SetFavoritePokemonProto other); // 362f60
public virtual void MergeFrom(CodedInputStream input); // 362f90
private static SetFavoritePokemonProto <_parser>m__20A(); // 362fc0
}

Have you witnessed a pokemon that fails and have you tried it in the official client? i have a feeling its a bug on niantics end and its going to cause type issues if its changed to unsigned again

@earshel
Copy link
Author

earshel commented Aug 17, 2016

@Grover-c13 I see that, and I think I have the answer. Per this thread http://stackoverflow.com/questions/25556017/how-to-use-the-unsigned-integer-in-java-8:

In the oracle "Primitive data types" page, it mentions that java 8 adds support for unsinged ints and longs:

long: The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -2^63 and a maximum value of 2^63-1. In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 2^64-1. Use this data type when you need a range of values wider than those provided by int. The Long class also contains methods like compareUnsigned, divideUnsigned etc to support arithmetic operations for unsigned long.

So while the game client is declaring it as a "long", it is being interpreted as an unsigned long automatically. In Python, it's necessary to declare the variable as an unsigned int64. I know nothing about Java, but this is what my research has lead me to believe.

@Grover-c13
Copy link
Contributor

The dump is not java

@earshel
Copy link
Author

earshel commented Aug 17, 2016

@Grover-c13 Well, then I'm at a loss. I posted proof of the issue above, and I've done my best to try to determine where the discrepancy is ;(. All I can really tell you is that Pokemon whose ID fall outside of the scope of INT64 can't be favorited because of this proto, and that using UINT64 instead resolves the issue. I've made this change in the proto on my end and I've been using it without issue for several days now. At this point, I don't care to continue trying to prove anything, especially since the author hasn't chimed in.

@Grover-c13
Copy link
Contributor

Not saying i dont believe you :P just saying we need to try and find a solution to cover most languages which can be difficult given the nature of protobuf. AeonLucid is probably busy and may not even know/had this issue, so i don't think his input should stop us determining a good solution at this point.

If you look at #126 we had some type issues between it. Originally we had it as fixed64 but it did not work, so we tried unit64 which worked for java but not for @GrimmGringo and uses C#. The original logic behind it was the game client is using signed longs for setFavouritePokemon (from decoded client in c++), which is odd because everything else doesnt, so i thought the client might have a bug on pokemon ids > long.max when setting favorite, unless the server has the correct type of ulong and is handling the long being sent.

Just out of curiosity could you try and favorite the pokemon inside the game and see if it works?

@earshel
Copy link
Author

earshel commented Aug 18, 2016

Fair enough. I identified a problem Pokemon and favorited it in the game client no problem. For what it's worth, the untouched compiled protos for releasePokemon,evolvePokemon,upgradePokemon all use type=6 (fixed64) and cpp_type=4(uint64), while the setFavoritePokemon uses type=3(int64) and cpp_type=2(int64). Why this proto message uses different datatypes, which cause it to fail, I dunno. Here's the fieldDescriptor reference I am using to determine all of this: https://developers.google.com/protocol-buffers/docs/reference/python/google.protobuf.descriptor.FieldDescriptor-class

@AeonLucid
Copy link
Owner

Closing this issue, let me know if this is still relevant.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants