Skip to content

Commit

Permalink
Fix entities (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tides authored Sep 18, 2024
1 parent 8935b46 commit 972d229
Show file tree
Hide file tree
Showing 29 changed files with 488 additions and 471 deletions.
19 changes: 16 additions & 3 deletions Obsidian.API/Configuration/ServerConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
using Obsidian.API.Configuration;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;

namespace Obsidian.API.Configuration;

public sealed class ServerConfiguration
{
private byte viewDistance = 10;
private byte simulationDistance = 10;
private ushort entityBroadcastRangePercentage = 100;

// Anything lower than 3 will cause weird artifacts on the client.
private const byte MinimumViewDistance = 3;

private const byte MinimumSimulationDistance = 5;
/// <summary>
/// Enabled Remote Console operation.
/// </summary>
Expand Down Expand Up @@ -84,6 +85,18 @@ public byte ViewDistance
set => viewDistance = value >= MinimumViewDistance ? value : MinimumViewDistance;
}

public byte SimulationDistance
{
get => simulationDistance;
set => simulationDistance = value > this.ViewDistance ? value >= MinimumSimulationDistance ? value : MinimumSimulationDistance : ViewDistance;
}

public ushort EntityBroadcastRangePercentage
{
get => entityBroadcastRangePercentage;
set => Math.Max((ushort)10, value);
}

public int PregenerateChunkRange { get; set; } = 15; // by default, pregenerate range from -15 to 15;

public ServerListQuery ServerListQuery { get; set; } = ServerListQuery.Full;
Expand Down
18 changes: 17 additions & 1 deletion Obsidian.API/_Enums/Pose.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,21 @@ public enum Pose : int

Sneaking,

Dying
LongJumper,

Dying,

Croaking,

UsingTongue,

Sitting,

Roaring,

Smiffing,

Emerging,

Digging
}
25 changes: 17 additions & 8 deletions Obsidian.API/_Interfaces/IEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,25 @@ public interface IEntity
public bool Summonable { get; }
public bool IsFireImmune { get; }

public Task RemoveAsync();
public Task TickAsync();
public Task DamageAsync(IEntity source, float amount = 1.0f);
public ValueTask RemoveAsync();
public ValueTask TickAsync();
public ValueTask DamageAsync(IEntity source, float amount = 1.0f);

public Task KillAsync(IEntity source);
public Task KillAsync(IEntity source, ChatMessage message);
public ValueTask KillAsync(IEntity source);
public ValueTask KillAsync(IEntity source, ChatMessage message);

public Task TeleportAsync(IWorld world);
public Task TeleportAsync(IEntity to);
public Task TeleportAsync(VectorF pos);
public ValueTask TeleportAsync(IWorld world);
public ValueTask TeleportAsync(IEntity to);
public ValueTask TeleportAsync(VectorF pos);

public bool IsInRange(IEntity entity, float distance);

/// <summary>
/// Spawns the specified entity to player nearby in the world.
/// </summary>
/// <param name="velocity">The velocity the entity should spawn with</param>
/// <param name="additionalData">Additional data for the entity. More info here: <see href="https://wiki.vg/Object_Data"/></param>
public void SpawnEntity(Velocity? velocity = null, int additionalData = 0);

public IEnumerable<IEntity> GetEntitiesNear(float distance);

Expand Down
20 changes: 8 additions & 12 deletions Obsidian.API/_Interfaces/IWorld.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Collections.Concurrent;

namespace Obsidian.API;

public interface IWorld : IAsyncDisposable
Expand All @@ -20,20 +18,18 @@ public interface IWorld : IAsyncDisposable
public int LoadedChunkCount { get; }
public int ChunksToGenCount { get; }

public int GetTotalLoadedEntities();

public Task<IBlock?> GetBlockAsync(Vector location);
public Task<IBlock?> GetBlockAsync(int x, int y, int z);
public Task SetBlockAsync(Vector location, IBlock block);
public Task SetBlockAsync(int x, int y, int z, IBlock block);
public ValueTask<IBlock?> GetBlockAsync(Vector location);
public ValueTask<IBlock?> GetBlockAsync(int x, int y, int z);
public ValueTask SetBlockAsync(Vector location, IBlock block);
public ValueTask SetBlockAsync(int x, int y, int z, IBlock block);

public Task SetBlockUntrackedAsync(int x, int y, int z, IBlock block, bool doBlockUpdate);
public ValueTask SetBlockUntrackedAsync(int x, int y, int z, IBlock block, bool doBlockUpdate);

public Task SetBlockUntrackedAsync(Vector location, IBlock block, bool doBlockUpdate);
public ValueTask SetBlockUntrackedAsync(Vector location, IBlock block, bool doBlockUpdate);

public Task<int?> GetWorldSurfaceHeightAsync(int x, int z);
public ValueTask<int?> GetWorldSurfaceHeightAsync(int x, int z);

public Task<IEntity> SpawnEntityAsync(VectorF position, EntityType type);
public IEntity SpawnEntity(VectorF position, EntityType type);
public void SpawnExperienceOrbs(VectorF position, short count);

public Task DoWorldTickAsync();
Expand Down
30 changes: 25 additions & 5 deletions Obsidian/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ public sealed class Client : IDisposable
/// The connection context associated with the <see cref="networkStream"/>.
/// </summary>
private readonly ConnectionContext connectionContext;
private readonly ILoggerFactory loggerFactory;

/// <summary>
/// Whether the stream has encryption enabled. This can be set to false when the client is connecting through LAN or when the server is in offline mode.
Expand Down Expand Up @@ -155,7 +156,7 @@ public sealed class Client : IDisposable
/// <summary>
/// Used to log actions caused by the client.
/// </summary>
public ILogger Logger { get; }
public ILogger Logger { get; private set; }

/// <summary>
/// The player that the client is logged in as.
Expand All @@ -168,13 +169,13 @@ public sealed class Client : IDisposable
/// </summary>
public string? Brand { get; set; }

public Client(ConnectionContext connectionContext, int playerId,
public Client(ConnectionContext connectionContext,
ILoggerFactory loggerFactory, IUserCache playerCache,
Server server)
{
this.connectionContext = connectionContext;
this.loggerFactory = loggerFactory;

id = playerId;
LoadedChunks = [];
packetCryptography = new();
handler = new(server.Configuration);
Expand All @@ -183,7 +184,7 @@ public Client(ConnectionContext connectionContext, int playerId,

this.server = server;
this.userCache = playerCache;
this.Logger = loggerFactory.CreateLogger($"Client{playerId}");
this.Logger = loggerFactory.CreateLogger("ConnectionHandler");

missedKeepAlives = [];
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
Expand Down Expand Up @@ -330,7 +331,16 @@ public async Task StartConnectionAsync()
if (result == EventResult.Cancelled)
return;

await handler.HandlePlayPackets(id, data, this);
try
{
await handler.HandlePlayPackets(id, data, this);
}
catch (Exception ex)
{
this.Logger.LogDebug(ex, "Exception thrown");
}


break;
case ClientState.Closed:
default:
Expand Down Expand Up @@ -442,6 +452,8 @@ private async Task HandleLoginStartAsync(byte[] data)
return;
}

this.InitializeId();

Player = new Player(this.cachedUser.Uuid, loginStart.Username, this, world);
packetCryptography.GenerateKeyPair();

Expand All @@ -462,6 +474,8 @@ private async Task HandleLoginStartAsync(byte[] data)
}
else
{
this.InitializeId();

Player = new Player(GuidHelper.FromStringHash($"OfflinePlayer:{username}"), username, this, world);

this.SendPacket(new LoginSuccess(Player.Uuid, Player.Username)
Expand All @@ -471,6 +485,12 @@ private async Task HandleLoginStartAsync(byte[] data)
}
}

private void InitializeId()
{
this.id = Server.GetNextEntityId();
this.Logger = this.loggerFactory.CreateLogger($"Client({this.id})");
}

private async Task HandleEncryptionResponseAsync(byte[] data)
{
if (Player is null)
Expand Down
4 changes: 2 additions & 2 deletions Obsidian/Commands/MainCommandModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ public async Task SpawnEntityAsync(string entityType)
return;
}

await player.World.SpawnEntityAsync(player.Position, type);
player.World.SpawnEntity(player.Position, type);
await player.SendMessageAsync($"Spawning: {type}");
}

Expand All @@ -342,7 +342,7 @@ public async Task DerpAsync(string entityType)
return;
}

var frogge = await player.World.SpawnEntityAsync(player.Position, type);
var frogge = player.World.SpawnEntity(player.Position, type);
var server = (this.Server as Server)!;

_ = Task.Run(async () =>
Expand Down
4 changes: 2 additions & 2 deletions Obsidian/Entities/AbstractHorse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public async override Task WriteAsync(MinecraftStream stream)
await stream.WriteEntityMetdata(16, EntityMetadataType.Byte, this.HorseMask);

if (this.Owner != default)
await stream.WriteEntityMetdata(17, EntityMetadataType.OptUuid, Owner, true);
await stream.WriteEntityMetdata(17, EntityMetadataType.OptionalUUID, Owner, true);
}

public override void Write(MinecraftStream stream)
Expand All @@ -25,7 +25,7 @@ public override void Write(MinecraftStream stream)
stream.WriteEntityMetadataType(16, EntityMetadataType.Byte);
stream.WriteUnsignedByte((byte)HorseMask);

stream.WriteEntityMetadataType(17, EntityMetadataType.OptUuid);
stream.WriteEntityMetadataType(17, EntityMetadataType.OptionalUUID);
stream.WriteBoolean(true);
if (true)
stream.WriteUuid(Owner);
Expand Down
Loading

0 comments on commit 972d229

Please sign in to comment.