These are chat archives for ProtoDef-io/node-protodef

8th
Apr 2017
mhsjlw
@mhsjlw
Apr 08 2017 12:39
@hansihe I finally pulled my head out of my ass and said I'm going to try ProtoDef elixir
I'm glad I did, thank you for making it :D
I just took some time and read McProtocol and I understand things now
I think I needed some more Elixir experience as well, but it all tied together
also, is size of just not required ?
Hans Elias J.
@hansihe
Apr 08 2017 12:51
nope, not really. it writes the output data to iolists
mhsjlw
@mhsjlw
Apr 08 2017 12:52
ok nice
just one question though
i've got every data type so far
i just need that one
and read to byte
how exactly do I do those?
Hans Elias J.
@hansihe
Apr 08 2017 12:53
describe what you want to do
mhsjlw
@mhsjlw
Apr 08 2017 12:53
I am defining ProtoDefTypes right now
for exampkle
def encode_magic(data) do
    << 0, 255, 255, 0, 254, 254, 254, 254, 253, 253, 253, 253, 18, 52, 86, 120 >>
  end

  def decode_magic(data) do
    << 0, 255, 255, 0, 254, 254, 254, 254, 253, 253, 253, 253, 18, 52, 86, 120 >> = data
    {{<< 0, 255, 255, 0, 254, 254, 254, 254, 253, 253, 253, 253, 18, 52, 86, 120 >>}, data}
  end
"magic" => {:simple,
      {__MODULE__, :encode_magic},
      {__MODULE__, :decode_magic}},
I am trying to compile the raknet protocol json
Hans Elias J.
@hansihe
Apr 08 2017 12:54
i mean the type you linked
mhsjlw
@mhsjlw
Apr 08 2017 12:54
i have no idea wtf that is
rom wrote it
oh
Hans Elias J.
@hansihe
Apr 08 2017 12:54
well, that should be your first priority then, figure out what you want it to do
mhsjlw
@mhsjlw
Apr 08 2017 12:54
I think it reads the i16 as a byte?
is that even valid
value<<3
yeah
i think it goes short to byte
wait
i failed bitwise operators
and graph theory
one second
Math.ceil(results.value/8)
that's what it is
it divides by 8 and ceils it
mhsjlw
@mhsjlw
Apr 08 2017 13:05
hmm
mhsjlw
@mhsjlw
Apr 08 2017 13:32
oh actually
@hansihe how do I do this
because it uses typeArgs
does elixir-protodef have that ?
or should I just hardcode it to i16 since that's the only type it's used for?
Hans Elias J.
@hansihe
Apr 08 2017 13:33
you could do it, but it would involve adding a new type to the compiler
the easy way would be to hardcode it
mhsjlw
@mhsjlw
Apr 08 2017 13:33
yeah, let's not do that
yeah ok i'll just do that
readEndOfArray
I think what this does is just read to the rest of the buffer with a specified type
shit
"type": [
            "endOfArray",
            {
              "type": [
                "encapsulated_packet",
                {
                  "internal": false
                }
              ]
            }
          ]
it reads a custom type
how can I implement end of array without this.read and typeArgs
damn
it's not size prefixed so it just reads to the end of the buffer
hmmm
Hans Elias J.
@hansihe
Apr 08 2017 13:36
you would probably just implement that as elixir code
it doesn't get used from anywhere else in the protodef file
mhsjlw
@mhsjlw
Apr 08 2017 13:37
but how do i read encapsulated packet then
Hans Elias J.
@hansihe
Apr 08 2017 13:37
call the elixir function?
mhsjlw
@mhsjlw
Apr 08 2017 13:37
which is ... lol
sorry
it's a protodef type ?
Hans Elias J.
@hansihe
Apr 08 2017 13:38
what?
sorry, I think I misunderstood you
mhsjlw
@mhsjlw
Apr 08 2017 13:38
encapsulated_packet is a protodef implemented function
i can't just 'call the function'
because there is no encode decode that i can see
Hans Elias J.
@hansihe
Apr 08 2017 13:39
well, the compiler takes a protodef type and compiles it to elixir code
so you can call it after you compiled it
Hans Elias J.
@hansihe
Apr 08 2017 13:50
just to explain once more what I actually mean
instead of using the protodef compiler on the packet_data_packet type
use it on the EncapsulatedPacket type instead
then implement what packet_data_packet does in elixir code, and call EncapsulatedPacket from it
packet_data_packet doesn't actually do that much
mhsjlw
@mhsjlw
Apr 08 2017 14:16
heck no
that's what i was doing earlier
and it's the most ridiculous fucking thing
*encapsulated
i'd rather keep this as much to protodef as possible
hmm
Hans Elias J.
@hansihe
Apr 08 2017 14:24
okey, then you are going to have to improve the compiler
mhsjlw
@mhsjlw
Apr 08 2017 14:24
rip
mhmmhmhmmh
well
i don't want to do either things
how do i do the first thing though
because i have no idea how i'd 'improve the compiler' without breaking everything
so i'm not going to even consider that
@hansihe ^
Hans Elias J.
@hansihe
Apr 08 2017 14:36
well, you would use the compiler to compile the EncapsulatedPacket type
then you define that as a function
then you would implement what EncapsulatedPacket does in elixir code
sorry
no wait
I copy pasted the wrong name, let me start again
well, you would use the compiler to compile the packet_data_packet type
then you define that as a function
then you would implement what EncapsulatedPacket does in elixir code
using the packet_data_packet you defined earlier
mhsjlw
@mhsjlw
Apr 08 2017 14:40
firstly
actually wait
okay so
where my types are
i want to implement encapsulated packet
no wait
wtf
i'm so confused
let me re read
OH
so register encapsulated_packet as a native type
then compile data_packet
encapsulated packet is like the most fucking complex packet in this entire spec though
ugh
it's the only reason why i wanted to use protodef
urg
wait
don't you mean compile EncapsulatedPacket then implement data_packet in elixir code ?
it's data_packet which uses the endOfArray
@hansihe
Hans Elias J.
@hansihe
Apr 08 2017 14:44
yes
mhsjlw
@mhsjlw
Apr 08 2017 14:45
okay okay
i can do this
i think
well actually
can you have recursive functions with this
because i need to loop over the data
@hansihe is an 'array' in js a list in elixir ?
Hans Elias J.
@hansihe
Apr 08 2017 14:51
the array type in protodef corresponds to an elixir list, yes
mhsjlw
@mhsjlw
Apr 08 2017 14:51
  def encode_data_packet(data) do
      binary = << data[:sequence_number] :: little-size(24) >>
      [head | tail] = data[:encapsulated_packets]
      encode_data_packet(tail, binary ++ head)
  end

  def encode_data_packet(packets, binary) do
      [head | tail] = packets

      encode_data_packet(packets, binary ++ head)
  end

  def encode_data_packet([], binary) do
      binary
  end
    "packet_data_packet" => {:simple,
      {__MODULE__, :encode_data_packet},
      {__MODULE__, :decode_data_packet}}
does that work ?
i've made some modifications to the json to improve understanding
seqNumber -> sequence_number
wait i fixed something in the first one
i passed packets not tail
*second
Hans Elias J.
@hansihe
Apr 08 2017 14:53
there are a couple of things wrong with the first one
do you know what an iolist is?
mhsjlw
@mhsjlw
Apr 08 2017 14:54
from erlang ya
Hans Elias J.
@hansihe
Apr 08 2017 14:54
the ++ operator is for lists only
binary is a binary
mhsjlw
@mhsjlw
Apr 08 2017 14:55
uh ? no
Hans Elias J.
@hansihe
Apr 08 2017 14:55
binary = << data[:sequence_number] :: little-size(24) >>
yes
it is
mhsjlw
@mhsjlw
Apr 08 2017 14:55
really ?
wait
oh
Hans Elias J.
@hansihe
Apr 08 2017 14:55
<<>> is binary pattern syntax
mhsjlw
@mhsjlw
Apr 08 2017 14:55
yeah
Hans Elias J.
@hansihe
Apr 08 2017 14:55
binary is a binary
mhsjlw
@mhsjlw
Apr 08 2017 14:55
yes
but this is lists
oh
Hans Elias J.
@hansihe
Apr 08 2017 14:55
++ doesn't work on binaries
it only works on lists
mhsjlw
@mhsjlw
Apr 08 2017 14:56
i thought it did, yeah
sorry
Hans Elias J.
@hansihe
Apr 08 2017 14:58
also, you are not actually calling EncapsulatedPacket from anywhere in that function
you are also doing the recursion in that code in a really really strange way
mhsjlw
@mhsjlw
Apr 08 2017 14:58
ok ,so
let's break this down
yeahi fixed the recursion
wrong order of functions
i have no idea how to call encapsulated packet
yeah i need to call encapsulated packet first before I add it to the data
but i can't append them
@hansihe how do I call encapsulated_packets firstly
Hans Elias J.
@hansihe
Apr 08 2017 15:00
have you compiled EncapsulatedPacket and defined it as a function?
you should do that, and then call that function
mhsjlw
@mhsjlw
Apr 08 2017 15:00
ok i'm overwhelmed right now
i cant get shit to work
the mcprotocol thing for generating packets
i cant even get that to work
let alone remove the data packet one
it calls extract packet mappings
i read the source code for that
no idea what it does
let me find an elixir playground
mhsjlw
@mhsjlw
Apr 08 2017 15:06
raw_data = Poison.decode!(File.read!("protocol.json"))

packets = raw_data
|> Enum.filter(fn {name, _} -> name != "types" end)
|> Enum.flat_map(fn {state_name, directions} ->
  Enum.map(directions, fn {data} ->
    types = data["types"]

    packet_map_type = types["packet"]
    packets = McProtocol.Packet.Utils.extract_packet_mappings(packet_map_type)

    %{
      packets: packets,
      types: types,
    }
  end)
end)
i've made this more of a mess
so i'm guessing what i end up wanting is a list of maps
or wait
a map with packets and types
@hansihe i have no idea what i'm doing
Hans Elias J.
@hansihe
Apr 08 2017 15:13
remember what the the compiler does
it takes a protodef type in json format and compiles it into an elixir ast
that's all it does
you are responsible for doing everything else
mhsjlw
@mhsjlw
Apr 08 2017 15:14
packets = raw_data |> Enum.filter(fn {name, _} -> name != "types" end)
whywhyhwhy
then it just returns []
Hans Elias J.
@hansihe
Apr 08 2017 15:14
you know what that does?
mhsjlw
@mhsjlw
Apr 08 2017 15:15
it filters it out if fun isn't truthy >
returns if it is trutyh
no idea wtf flat map is
i have no idea honestly what this is actually supposed to do
Hans Elias J.
@hansihe
Apr 08 2017 15:15
yeah, but in the context of a protocol.json file?
mhsjlw
@mhsjlw
Apr 08 2017 15:16
i'm guessing it grabs all types and all packet definitions and adds them to map
Hans Elias J.
@hansihe
Apr 08 2017 15:16
what does that specifically do?
mhsjlw
@mhsjlw
Apr 08 2017 15:16
but i have special packet types as well
yes
it's the entire file
raw_data = Poison.decode!(File.read!("protocol.json"))
i have a special case though
i need to compile the packets inside of packets as well
mhsjlw
@mhsjlw
Apr 08 2017 15:29
@hansihe Enum.filter(fn {name, _} -> name != "types" end) this makes no sense though
it will always return []
types is the root element
Hans Elias J.
@hansihe
Apr 08 2017 15:32
no it isn't
mhsjlw
@mhsjlw
Apr 08 2017 15:32
ok then why isn't it working then
Hans Elias J.
@hansihe
Apr 08 2017 15:32
in a protocol.json file the root element is an object
there is a single key "types" that contains the type
mhsjlw
@mhsjlw
Apr 08 2017 15:33
yes
Hans Elias J.
@hansihe
Apr 08 2017 15:33
then the other keys in that root object are namespaces
mhsjlw
@mhsjlw
Apr 08 2017 15:33
Filters the enumerable, i.e. returns only those elements for which fun returns a truthy value.
so when you say name != types
then it will return nothing
Hans Elias J.
@hansihe
Apr 08 2017 15:33
yes
because you want all of the namespaces
mhsjlw
@mhsjlw
Apr 08 2017 15:33
i don't
because everything is inside types
there is nothing else
Hans Elias J.
@hansihe
Apr 08 2017 15:33
well, so change it then
that code was written for the minecraft_data protocol.json file
mhsjlw
@mhsjlw
Apr 08 2017 15:34
ok
mhsjlw
@mhsjlw
Apr 08 2017 15:40
@hansihe can you tell me what packets needs to be
and i will try to get that
Hans Elias J.
@hansihe
Apr 08 2017 15:42
I think your use-case is adequately different from the one that MCProtocol has that you shouldn't really directly copy it and just change things
you should remember that ProtoDef.compile_json_type takes a json type as its input and produces an ast for both a serialization and deserialization function
so you should think about your usecase and decide where you would want your type functions defined, and transform the protocol part of your protocol.json in such a way that it best suits what you want to do
so, the ProtoDef.compile_json_type would take this as an argument https://github.com/mhsjlw/node-raknet/blob/master/data/protocol.json#L71-L85
it's up to you to decide everything else
mhsjlw
@mhsjlw
Apr 08 2017 16:09
ok
i'm going to have to make my own pipeline for data packets then
which i guess is what i want
the api exposed with elixir raknet will likely be a listen function then pass a genserver
then functions for sending data packets to the current client
and having a gen server for each client
that's what i can think of
how does mcprotocol do it ?