v0.1.3
This version introduces some new changes, most of which don't affect the users but the API internally.
New context methods:
-
Context.reply(packet: Packet) -> bool
The
Context.reply
method is used to send a packet to a peer. This method simply allows for easy access (you wouldn't have to go on about accessing the player attr yourself likecontext.player(or client).send(packet)
).
New context classes:
ClientContext
ServerContext
The ClientContext
is used by clients (Client
, GameClient
, ProxyClient
, etc.) This is to simply avoid confusion that may happen when handling client events.
The ServerContext
is used by servers (Server
, LoginServer
, ProxyServer
, etc.) This is to simply avoid confusion that may happen when handling server events.
The ClientContext
and ServerContext
classes use the Context
class as base for some shared attributes (packet
, enet_event
, etc.)
Removed stuff
-
Host class
The
Host
class was meant to handle some base stuff, like the servicing bit, and then it was meant to call a method that a child class would have implemented to handle the incoming packet. This idea is still valid and will be implemented in the near future.Things that have changed
-
Different packet base for specific packet types
A packet's base is now specific to its contents. Meaning that if the packet contains text it'd use the class StrPacket
as base instead of the original Packet
class. This is to allow users to create string packets easily.
Before, this wasn't possible as the Packet
class only took in bytes/bytearrays (since I made it so that you'd only provide the data arg if you're deserialising.)
GameMessagePacket("action|log\nmsg|hi!")
The old way is still possible, though both GameMessagePacket
and TextPacket
have their text value in the attribute text
unlike before, where GameMessagePacket
had it in the attribute game_message
game_message_packet = GameMessagePacket()
game_message_packet.text = "action|log\nmsg|hi!"
- Game update packet initialisation
Users are now able to instantiate a GameUpdatePacket
object with specific fields by passing them as kwargs.
GameUpdatePacket(update_type=GameUpdatePacketType.CALL_FUNCTION, variant_list=VariantList("OnConsoleMessage", "Hello!"))
The old way of setting those fields is still possible.
packet = GameUpdatePacket()
packet.update_type = GameUpdatePacketType.CALL_FUNCTION
packet.set_variant_list(VariantList("OnConsoleMessage", "Hello!"))
- Deserialising packets
In order to deserialise a packet (bytes -> object) you'd use the new classmethodfrom_bytes
for all packet types.
E.g the server sends a game message packet with text "action|log\nmsg|hi!\n", you'd deserialise it like the following:
packet = GameMessagePacket.from_bytes(b"\x03\x00\x00\x00action|log\nmsg|hi!\n")
# The packet's now deserialised and you may view its contents through a couple of new attributes:
print(packet.action, packet.argument["msg"]) # log, hi!
You can no longer pass bytes to any packet's initialiser.
- New attributes
2 new attributes were added to the GameMessagePacket
and TextPacket
classes (since their base changed to StrPacket
, the classes inherited those new attributes.)
- action ~ set when a packet contains
action|<action>
- arguments ~ set when a packet contains the above with arguments
action|<action>\n<arg_name>|<arg_value>
You may also use those attributes when sending a StrPacket
(TextPacket
/GameMessagePacket
).
log_action_packet = GameMessagePacket()
log_action_packet.action = "log"
log_action_packet.arguments["msg"] = "hello!"
print(log_action_packet.serialise()) # b'\x03\x00\x00\x00action|log\nmsg|hello!\n'
--------------------
# You can now set kvps and have them serialised too! (you may use this for the login packet, though you can already use PlayerLoginInfo for that.)
random_kvp_test_packet = TextPacket()
random_kvp_test_packet.kvps["key1"] = "value1"
random_kvp_test_packet.kvps["key2"] = "value2"
random_kvp_test_packet.kvps["key3"] = "value3"
print(random_kvp_test_packet.serialise()) # b'\x02\x00\x00\x00key1|value1\nkey2|value2\nkey3|value3\n'