Skip to content

Commit 972d229

Browse files
authored
Fix entities (#450)
1 parent 8935b46 commit 972d229

29 files changed

+488
-471
lines changed

Obsidian.API/Configuration/ServerConfiguration.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
using Obsidian.API.Configuration;
2-
using System.Text.Json.Serialization;
1+
using System.Text.Json.Serialization;
32

43
namespace Obsidian.API.Configuration;
54

65
public sealed class ServerConfiguration
76
{
87
private byte viewDistance = 10;
8+
private byte simulationDistance = 10;
9+
private ushort entityBroadcastRangePercentage = 100;
910

1011
// Anything lower than 3 will cause weird artifacts on the client.
1112
private const byte MinimumViewDistance = 3;
12-
13+
private const byte MinimumSimulationDistance = 5;
1314
/// <summary>
1415
/// Enabled Remote Console operation.
1516
/// </summary>
@@ -84,6 +85,18 @@ public byte ViewDistance
8485
set => viewDistance = value >= MinimumViewDistance ? value : MinimumViewDistance;
8586
}
8687

88+
public byte SimulationDistance
89+
{
90+
get => simulationDistance;
91+
set => simulationDistance = value > this.ViewDistance ? value >= MinimumSimulationDistance ? value : MinimumSimulationDistance : ViewDistance;
92+
}
93+
94+
public ushort EntityBroadcastRangePercentage
95+
{
96+
get => entityBroadcastRangePercentage;
97+
set => Math.Max((ushort)10, value);
98+
}
99+
87100
public int PregenerateChunkRange { get; set; } = 15; // by default, pregenerate range from -15 to 15;
88101

89102
public ServerListQuery ServerListQuery { get; set; } = ServerListQuery.Full;

Obsidian.API/_Enums/Pose.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,21 @@ public enum Pose : int
1414

1515
Sneaking,
1616

17-
Dying
17+
LongJumper,
18+
19+
Dying,
20+
21+
Croaking,
22+
23+
UsingTongue,
24+
25+
Sitting,
26+
27+
Roaring,
28+
29+
Smiffing,
30+
31+
Emerging,
32+
33+
Digging
1834
}

Obsidian.API/_Interfaces/IEntity.cs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,25 @@ public interface IEntity
4444
public bool Summonable { get; }
4545
public bool IsFireImmune { get; }
4646

47-
public Task RemoveAsync();
48-
public Task TickAsync();
49-
public Task DamageAsync(IEntity source, float amount = 1.0f);
47+
public ValueTask RemoveAsync();
48+
public ValueTask TickAsync();
49+
public ValueTask DamageAsync(IEntity source, float amount = 1.0f);
5050

51-
public Task KillAsync(IEntity source);
52-
public Task KillAsync(IEntity source, ChatMessage message);
51+
public ValueTask KillAsync(IEntity source);
52+
public ValueTask KillAsync(IEntity source, ChatMessage message);
5353

54-
public Task TeleportAsync(IWorld world);
55-
public Task TeleportAsync(IEntity to);
56-
public Task TeleportAsync(VectorF pos);
54+
public ValueTask TeleportAsync(IWorld world);
55+
public ValueTask TeleportAsync(IEntity to);
56+
public ValueTask TeleportAsync(VectorF pos);
57+
58+
public bool IsInRange(IEntity entity, float distance);
59+
60+
/// <summary>
61+
/// Spawns the specified entity to player nearby in the world.
62+
/// </summary>
63+
/// <param name="velocity">The velocity the entity should spawn with</param>
64+
/// <param name="additionalData">Additional data for the entity. More info here: <see href="https://wiki.vg/Object_Data"/></param>
65+
public void SpawnEntity(Velocity? velocity = null, int additionalData = 0);
5766

5867
public IEnumerable<IEntity> GetEntitiesNear(float distance);
5968

Obsidian.API/_Interfaces/IWorld.cs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using System.Collections.Concurrent;
2-
31
namespace Obsidian.API;
42

53
public interface IWorld : IAsyncDisposable
@@ -20,20 +18,18 @@ public interface IWorld : IAsyncDisposable
2018
public int LoadedChunkCount { get; }
2119
public int ChunksToGenCount { get; }
2220

23-
public int GetTotalLoadedEntities();
24-
25-
public Task<IBlock?> GetBlockAsync(Vector location);
26-
public Task<IBlock?> GetBlockAsync(int x, int y, int z);
27-
public Task SetBlockAsync(Vector location, IBlock block);
28-
public Task SetBlockAsync(int x, int y, int z, IBlock block);
21+
public ValueTask<IBlock?> GetBlockAsync(Vector location);
22+
public ValueTask<IBlock?> GetBlockAsync(int x, int y, int z);
23+
public ValueTask SetBlockAsync(Vector location, IBlock block);
24+
public ValueTask SetBlockAsync(int x, int y, int z, IBlock block);
2925

30-
public Task SetBlockUntrackedAsync(int x, int y, int z, IBlock block, bool doBlockUpdate);
26+
public ValueTask SetBlockUntrackedAsync(int x, int y, int z, IBlock block, bool doBlockUpdate);
3127

32-
public Task SetBlockUntrackedAsync(Vector location, IBlock block, bool doBlockUpdate);
28+
public ValueTask SetBlockUntrackedAsync(Vector location, IBlock block, bool doBlockUpdate);
3329

34-
public Task<int?> GetWorldSurfaceHeightAsync(int x, int z);
30+
public ValueTask<int?> GetWorldSurfaceHeightAsync(int x, int z);
3531

36-
public Task<IEntity> SpawnEntityAsync(VectorF position, EntityType type);
32+
public IEntity SpawnEntity(VectorF position, EntityType type);
3733
public void SpawnExperienceOrbs(VectorF position, short count);
3834

3935
public Task DoWorldTickAsync();

Obsidian/Client.cs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ public sealed class Client : IDisposable
126126
/// The connection context associated with the <see cref="networkStream"/>.
127127
/// </summary>
128128
private readonly ConnectionContext connectionContext;
129+
private readonly ILoggerFactory loggerFactory;
129130

130131
/// <summary>
131132
/// 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.
@@ -155,7 +156,7 @@ public sealed class Client : IDisposable
155156
/// <summary>
156157
/// Used to log actions caused by the client.
157158
/// </summary>
158-
public ILogger Logger { get; }
159+
public ILogger Logger { get; private set; }
159160

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

171-
public Client(ConnectionContext connectionContext, int playerId,
172+
public Client(ConnectionContext connectionContext,
172173
ILoggerFactory loggerFactory, IUserCache playerCache,
173174
Server server)
174175
{
175176
this.connectionContext = connectionContext;
177+
this.loggerFactory = loggerFactory;
176178

177-
id = playerId;
178179
LoadedChunks = [];
179180
packetCryptography = new();
180181
handler = new(server.Configuration);
@@ -183,7 +184,7 @@ public Client(ConnectionContext connectionContext, int playerId,
183184

184185
this.server = server;
185186
this.userCache = playerCache;
186-
this.Logger = loggerFactory.CreateLogger($"Client{playerId}");
187+
this.Logger = loggerFactory.CreateLogger("ConnectionHandler");
187188

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

333-
await handler.HandlePlayPackets(id, data, this);
334+
try
335+
{
336+
await handler.HandlePlayPackets(id, data, this);
337+
}
338+
catch (Exception ex)
339+
{
340+
this.Logger.LogDebug(ex, "Exception thrown");
341+
}
342+
343+
334344
break;
335345
case ClientState.Closed:
336346
default:
@@ -442,6 +452,8 @@ private async Task HandleLoginStartAsync(byte[] data)
442452
return;
443453
}
444454

455+
this.InitializeId();
456+
445457
Player = new Player(this.cachedUser.Uuid, loginStart.Username, this, world);
446458
packetCryptography.GenerateKeyPair();
447459

@@ -462,6 +474,8 @@ private async Task HandleLoginStartAsync(byte[] data)
462474
}
463475
else
464476
{
477+
this.InitializeId();
478+
465479
Player = new Player(GuidHelper.FromStringHash($"OfflinePlayer:{username}"), username, this, world);
466480

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

488+
private void InitializeId()
489+
{
490+
this.id = Server.GetNextEntityId();
491+
this.Logger = this.loggerFactory.CreateLogger($"Client({this.id})");
492+
}
493+
474494
private async Task HandleEncryptionResponseAsync(byte[] data)
475495
{
476496
if (Player is null)

Obsidian/Commands/MainCommandModule.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ public async Task SpawnEntityAsync(string entityType)
323323
return;
324324
}
325325

326-
await player.World.SpawnEntityAsync(player.Position, type);
326+
player.World.SpawnEntity(player.Position, type);
327327
await player.SendMessageAsync($"Spawning: {type}");
328328
}
329329

@@ -342,7 +342,7 @@ public async Task DerpAsync(string entityType)
342342
return;
343343
}
344344

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

348348
_ = Task.Run(async () =>

Obsidian/Entities/AbstractHorse.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public async override Task WriteAsync(MinecraftStream stream)
1515
await stream.WriteEntityMetdata(16, EntityMetadataType.Byte, this.HorseMask);
1616

1717
if (this.Owner != default)
18-
await stream.WriteEntityMetdata(17, EntityMetadataType.OptUuid, Owner, true);
18+
await stream.WriteEntityMetdata(17, EntityMetadataType.OptionalUUID, Owner, true);
1919
}
2020

2121
public override void Write(MinecraftStream stream)
@@ -25,7 +25,7 @@ public override void Write(MinecraftStream stream)
2525
stream.WriteEntityMetadataType(16, EntityMetadataType.Byte);
2626
stream.WriteUnsignedByte((byte)HorseMask);
2727

28-
stream.WriteEntityMetadataType(17, EntityMetadataType.OptUuid);
28+
stream.WriteEntityMetadataType(17, EntityMetadataType.OptionalUUID);
2929
stream.WriteBoolean(true);
3030
if (true)
3131
stream.WriteUuid(Owner);

0 commit comments

Comments
 (0)