Skip to content

Commit

Permalink
Implement player abilities packet (#433)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheVeryStarlk committed Mar 6, 2024
1 parent 6e363ba commit 4ce9755
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 2 deletions.
5 changes: 4 additions & 1 deletion Obsidian.API/_Interfaces/IPlayer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Net;
using Obsidian.API._Types;
using System.Net;

namespace Obsidian.API;

Expand All @@ -21,6 +22,8 @@ public interface IPlayer : ILiving
public IPAddress? ClientIP { get; }
public Gamemode Gamemode { get; set; }

public PlayerAbility Abilities { get; }

public bool Sleeping { get; set; }
public bool InHorseInventory { get; set; }

Expand Down
11 changes: 11 additions & 0 deletions Obsidian.API/_Types/PlayerAbility.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Obsidian.API;

[Flags]
public enum PlayerAbility
{
None = 0x00,
Invulnerable = 0x01,
Flying = 0x02,
AllowFlying = 0x04,
CreativeMode = 0x08
}
4 changes: 4 additions & 0 deletions Obsidian/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,10 @@ internal async Task SendPlayerInfoAsync()
}

await QueuePacketAsync(new PlayerInfoUpdatePacket(dict));
await QueuePacketAsync(new PlayerAbilitiesPacket(true)
{
Abilities = Player.Abilities
});
}

internal void SendPacket(IClientboundPacket packet)
Expand Down
22 changes: 21 additions & 1 deletion Obsidian/Entities/Player.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This would be saved in a file called [playeruuid].dat which holds a bunch of NBT data.
// https://wiki.vg/Map_Format
using Microsoft.Extensions.Logging;
using Obsidian.API._Types;
using Obsidian.API.Events;
using Obsidian.API.Utilities;
using Obsidian.Nbt;
Expand Down Expand Up @@ -62,7 +63,24 @@ public sealed partial class Player : Living, IPlayer

public IBlock? LastClickedBlock { get; internal set; }

public Gamemode Gamemode { get; set; }
public Gamemode Gamemode
{
get => gamemode;
set
{
gamemode = value;

Abilities = Gamemode switch
{
Gamemode.Creative => PlayerAbility.CreativeMode | PlayerAbility.AllowFlying | PlayerAbility.Invulnerable,
Gamemode.Spectator => PlayerAbility.AllowFlying | PlayerAbility.Invulnerable,
Gamemode.Survival or Gamemode.Adventure or Gamemode.Hardcore => PlayerAbility.None,
_ => throw new ArgumentOutOfRangeException(nameof(Gamemode), Gamemode, "Unknown gamemode.")
};
}
}

public PlayerAbility Abilities { get; internal set; }

public IScoreboard? CurrentScoreboard { get; set; }

Expand Down Expand Up @@ -115,6 +133,8 @@ internal set

public IPAddress? ClientIP => (client.RemoteEndPoint as IPEndPoint)?.Address;

private Gamemode gamemode;

[SetsRequiredMembers]
internal Player(Guid uuid, string username, Client client, World world)
{
Expand Down
1 change: 1 addition & 0 deletions Obsidian/Net/ClientHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public void RegisterHandlers()
Packets.TryAdd(0x17, new SetPlayerPositionPacket());
Packets.TryAdd(0x18, new SetPlayerPositionAndRotationPacket());
Packets.TryAdd(0x19, new SetPlayerRotationPacket());
Packets.TryAdd(0x20, new PlayerAbilitiesPacket(false));
//Packets.TryAdd(0x15, PlayerMovement);
//Packets.TryAdd(0x16, VehicleMove);
//Packets.TryAdd(0x17, SteerBoat);
Expand Down
58 changes: 58 additions & 0 deletions Obsidian/Net/Packets/Play/Clientbound/PlayerAbilitiesPacket.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using Obsidian.API._Types;
using Obsidian.Entities;

namespace Obsidian.Net.Packets.Play.Clientbound;

public class PlayerAbilitiesPacket : IClientboundPacket, IServerboundPacket
{
public PlayerAbility Abilities { get; set; } = PlayerAbility.None;

public float FlyingSpeed { get; set; } = 0.05F;

public float FieldOfViewModifier { get; set; } = 0.1F;

public int Id { get; }

public PlayerAbilitiesPacket(bool toClient)
{
Id = toClient ? 0x36 : 0x20;
}

public void Serialize(MinecraftStream stream)
{
using var packetStream = new MinecraftStream();
packetStream.WriteByte((byte)Abilities);
packetStream.WriteFloat(FlyingSpeed);
packetStream.WriteFloat(FieldOfViewModifier);

stream.Lock.Wait();
stream.WriteVarInt(Id.GetVarIntLength() + (int)packetStream.Length);
stream.WriteVarInt(Id);
packetStream.Position = 0;
packetStream.CopyTo(stream);
stream.Lock.Release();
}

public void Populate(MinecraftStream stream)
{
Abilities = (PlayerAbility) stream.ReadByte();
}

public void Populate(byte[] data)
{
using var stream = new MinecraftStream(data);
Populate(stream);
}

public async ValueTask HandleAsync(Server server, Player player)
{
if (Abilities.HasFlag(PlayerAbility.Flying)
&& !Abilities.HasFlag(PlayerAbility.AllowFlying)
&& player.Gamemode is not Gamemode.Creative or Gamemode.Spectator)
{
await player.KickAsync("Cheating is not allowed!");
}

player.Abilities |= Abilities;
}
}

0 comments on commit 4ce9755

Please sign in to comment.