Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various improvements #71

Merged
merged 73 commits into from
Aug 14, 2024
Merged

Various improvements #71

merged 73 commits into from
Aug 14, 2024

Conversation

Klotzi111
Copy link
Contributor

Hi, I am using your repo to build my Minecraft bot and while doing so I continued developing your project.
I am doing this in my forked repo.

This pull request is a friendly note that I am doing this and you can take my changes from that fork anytime.

So you can merge this pull request or just cherry pick changes you like.

added `EntitySoundEffectPacket`, `ParticlePacket`, and `SoundEffectPacket`
Since the returned Task of AsyncEvent.Dispatch now always completes after all subscribers finished I inspected the places where await was used on such tasks. Removed the await in the most cases since that how it was before.
…provements

- added IVersionAwareSerializable to extend ISerializable with version specific logic like in the packets
- moved some core element serialization methods in their classes

fixes psu-de#68
@psu-de
Copy link
Owner

psu-de commented Aug 7, 2024

Hi,
first of all, thank you very much for contributing :)

However I get some exceptions when running the integration tests.
What minecraft version are you using? And a vanilla server or what brand?

Repository owner deleted a comment from elRatto21 Aug 7, 2024
/// </summary>
/// <param name="MessageId">The message ID + 1, used for validating message signature.</param>
/// <param name="Signature">The previous message's signature. Always 256 bytes and not length-prefixed.</param>
public sealed record DeleteMessagePacket(int MessageId, byte[]? Signature) : IPacket
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DeleteMessagePacket is a little bit different in 1.19.2

/// </summary>
/// <param name="Position">The position of the scoreboard.</param>
/// <param name="ScoreName">The unique name for the scoreboard to be displayed.</param>
public sealed record DisplayObjectivePacket(int Position, string ScoreName) : IPacket
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In 1.20 and before, the Position field is sent as a sbyte

/// End Combat packet
/// </summary>
/// <param name="Duration">Length of the combat in ticks</param>
public sealed record EndCombatPacket(int Duration) : IPacket
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In 1.19.4 and before, this packet had an additional entityId field


namespace MineSharp.Protocol.Packets.Clientbound.Play;
#pragma warning disable CS1591
public sealed record EntitySoundEffectPacket(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EntitySoundEffect packet changed in 1.19 and again in 1.19.3

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With all that differences between versions how should we deal with that?

  1. We could make the packet class able to handle all the versions. But that often means that the paket gets fields that are not used in other versions. So we need to make them nullable. And also need to document when (for which version) these nullable fields are used.

  2. Or alternatively we could create a implementation of that packet class for every version that changed something in that packet. This makes using the packet classes more straitforward since you really get all the fields it hat. But that would mean that for different versions difference PacketHandlers are required (and need to be registered with On<PACKET>).

I like option 2 more. What do you think?

Copy link
Owner

@psu-de psu-de Aug 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, i've been struggeling with this problem ever since I started this project...
I'd also go with Option 2. Not too long ago I did something similar with SystemChatMessagePacket. I used an abstract base class so the different versions don't have to be registered themselves.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw. don't worry if you don't want to bother implementing all different packet versions. I'll do it at some point when I'm bored...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we need an even more abstract/universal approach than that currently used in SystemChatMessagePacket. A system that is consistent between all packets.
I mean I would also do this with using inheritance of the base packet class. But all the possible version specific sub classes need to implement a common interface and need to be registered in a lookup table (per packet).

We should probably create an issue regarding that topic.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,
sorry it took a while....

I've updated this Issue, and tried to write down my thoughts.

This was referenced Aug 13, 2024
/// <param name="Experience">Total experience for this villager (always 0 for the wandering trader).</param>
/// <param name="IsRegularVillager">True if this is a regular villager; false for the wandering trader.</param>
/// <param name="CanRestock">True for regular villagers and false for the wandering trader.</param>
public sealed record MerchantOffersPacket(int WindowId, int Size, Trade[] Trades, int VillagerLevel, int Experience, bool IsRegularVillager, bool CanRestock) : IPacket
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in 1.18, Size is a byte, not varint

/// </summary>
/// <param name="Location">The position of the sign</param>
/// <param name="IsFrontText">Whether the opened editor is for the front or on the back of the sign</param>
public sealed record OpenSignEditorPacket(Position Location, bool IsFrontText) : IPacket
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsFrontText doesn't exist in 1.19.4

/// Data depends on the particle id.
/// Will be an empty buffer for most particles.
/// </param>
public sealed record ParticlePacket(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ParticleId was sent as a VarInt before 1.19

/// </summary>
/// <param name="EntityId">The entity ID</param>
/// <param name="EffectId">The effect ID</param>
public sealed record RemoveEntityEffectPacket(int EntityId, int EffectId) : IPacket
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EffectId was sent as a byte before 1.19

/// <param name="HasIcon">Indicates if the server has an icon.</param>
/// <param name="Icon">Optional icon bytes in the PNG format.</param>
/// <param name="EnforcesSecureChat">Indicates if the server enforces secure chat.</param>
public sealed record ServerDataPacket(Chat Motd, bool HasIcon, byte[]? Icon, bool EnforcesSecureChat) : IPacket
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packet was different in 1.18, and changed in 1.19, 1.19.2, 1.19.3 and 1.19.4

/// <param name="ExperienceBar">The experience bar value between 0 and 1</param>
/// <param name="Level">The experience level</param>
/// <param name="TotalExperience">The total experience points</param>
public sealed record SetExperiencePacket(float ExperienceBar, int Level, int TotalExperience) : IPacket
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for some reason, the order in which ExperienceBar and Level are sent changed in 1.19.2 and then again in 1.20.2


namespace MineSharp.Protocol.Packets.Clientbound.Play;
#pragma warning disable CS1591
public sealed record SoundEffectPacket(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packet was different in 1.18 and changed in .19.2 and 1.19.3

/// <param name="EmptyBlockLightMask">BitSet for empty block light sections</param>
/// <param name="SkyLightArrays">Array of sky light data</param>
/// <param name="BlockLightArrays">Array of block light data</param>
public sealed record UpdateLightPacket(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Until 1.19.4, there was a TrustEdges field

/// <param name="Value">The score to be displayed next to the entry</param>
/// <param name="DisplayName">The custom display name</param>
/// <param name="NumberFormat">The number format for the score</param>
public sealed record UpdateScorePacket(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packet changed in 1.20.3

@Klotzi111
Copy link
Contributor Author

I am currently having a problem with the players health. Upon joining the server sends the LoginPacket and in it there are fields like HasDeathLocation, DeathDimensionName and EnableRespawnScreen which indicate that the player is dead when they are set.
My problem now is that these fields are set but my player is not dead. The SetHealthPacket that is received little after then tells the correct health. Any ideas why the login packet says the player is dead?

@psu-de psu-de merged commit 4ac5bd7 into psu-de:main Aug 14, 2024
@psu-de
Copy link
Owner

psu-de commented Aug 14, 2024

Any ideas why the login packet says the player is dead?

Hm no... Did your last commit fix it?

@Klotzi111
Copy link
Contributor Author

Hm no... Did your last commit fix it?

Yes in that it now works without triggering my bot to auto disconnect (because I wait for the SetHealthPacket now that gives the correct health value).
But no in that the LoginPacket still says the player is dead which is wrong.

@Klotzi111
Copy link
Contributor Author

I added a lot of missing packets but there are still some missing. I will slowly add them as I find time to do so

@Klotzi111 Klotzi111 mentioned this pull request Aug 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants