first commit
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
using NitroxModel.DataStructures.GameLogic;
|
||||
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
|
||||
using NitroxModel.Packets;
|
||||
using NitroxServer.Communication.Packets.Processors.Abstract;
|
||||
using NitroxServer.GameLogic;
|
||||
using NitroxServer.GameLogic.Entities;
|
||||
|
||||
namespace NitroxServer.Communication.Packets.Processors;
|
||||
|
||||
public class EntityMetadataUpdateProcessor : AuthenticatedPacketProcessor<EntityMetadataUpdate>
|
||||
{
|
||||
private readonly PlayerManager playerManager;
|
||||
private readonly EntityRegistry entityRegistry;
|
||||
|
||||
public EntityMetadataUpdateProcessor(PlayerManager playerManager, EntityRegistry entityRegistry)
|
||||
{
|
||||
this.playerManager = playerManager;
|
||||
this.entityRegistry = entityRegistry;
|
||||
}
|
||||
|
||||
public override void Process(EntityMetadataUpdate packet, Player sendingPlayer)
|
||||
{
|
||||
if (!entityRegistry.TryGetEntityById(packet.Id, out Entity entity))
|
||||
{
|
||||
Log.Error($"Entity metadata {packet.NewValue.GetType()} updated on an entity unknown to the server {packet.Id}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryProcessMetadata(sendingPlayer, entity, packet.NewValue))
|
||||
{
|
||||
entity.Metadata = packet.NewValue;
|
||||
SendUpdateToVisiblePlayers(packet, sendingPlayer, entity);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendUpdateToVisiblePlayers(EntityMetadataUpdate packet, Player sendingPlayer, Entity entity)
|
||||
{
|
||||
foreach (Player player in playerManager.GetConnectedPlayers())
|
||||
{
|
||||
bool updateVisibleToPlayer = player.CanSee(entity);
|
||||
|
||||
// Always sync container/storage metadata to all visible players
|
||||
bool isContainerMetadata = IsContainerRelatedMetadata(packet.NewValue);
|
||||
|
||||
if (player != sendingPlayer && (updateVisibleToPlayer || isContainerMetadata))
|
||||
{
|
||||
player.SendPacket(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsContainerRelatedMetadata(EntityMetadata metadata)
|
||||
{
|
||||
// Check if metadata is related to containers/storage
|
||||
return metadata.GetType().Name.Contains("Container") ||
|
||||
metadata.GetType().Name.Contains("Storage") ||
|
||||
metadata.GetType().Name.Contains("Inventory");
|
||||
}
|
||||
|
||||
private bool TryProcessMetadata(Player sendingPlayer, Entity entity, EntityMetadata metadata)
|
||||
{
|
||||
return metadata switch
|
||||
{
|
||||
PlayerMetadata playerMetadata => ProcessPlayerMetadata(sendingPlayer, entity, playerMetadata),
|
||||
|
||||
// Always allow container/storage metadata updates for proper sync
|
||||
_ when IsContainerRelatedMetadata(metadata) => true,
|
||||
|
||||
// Allow metadata updates from any player by default
|
||||
_ => true
|
||||
};
|
||||
}
|
||||
|
||||
private bool ProcessPlayerMetadata(Player sendingPlayer, Entity entity, PlayerMetadata metadata)
|
||||
{
|
||||
if (sendingPlayer.GameObjectId == entity.Id)
|
||||
{
|
||||
sendingPlayer.EquippedItems.Clear();
|
||||
foreach (PlayerMetadata.EquippedItem item in metadata.EquippedItems)
|
||||
{
|
||||
sendingPlayer.EquippedItems.Add(item.Slot, item.Id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Log.WarnOnce($"Player {sendingPlayer.Name} tried updating metadata of another player's entity {entity.Id}");
|
||||
return false;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user