Megacity demo game for UOS
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

130 行
5.3 KiB

using System;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.NetCode;
using Unity.NetCode.Extensions;
using static Unity.Entities.SystemAPI;
using Random = Unity.Mathematics.Random;
namespace Unity.MegaCity.Gameplay
{
/// <summary>
/// System to set the player info.
/// </summary>
[BurstCompile]
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
public partial struct SetPlayerInfoSystem : ISystem
{
#region Jobs
[BurstCompile]
private partial struct FindAvailableNameJob : IJob
{
public NativeArray<BotNameElement> Names;
public NativeList<FixedString64Bytes> UsedNames;
public Random Random;
[BurstCompile]
public void Execute()
{
var availablePlayerNames = GetAvailableNames();
if (availablePlayerNames.Length == 0)
{
UsedNames.Clear();
availablePlayerNames = GetAvailableNames();
}
// Choose a random player name from the list of available player names
var randomIndex = Random.NextInt(0, availablePlayerNames.Length);
var botName = availablePlayerNames[randomIndex];
UsedNames.Add(botName);
}
private NativeList<FixedString64Bytes> GetAvailableNames()
{
var availablePlayerNames = new NativeList<FixedString64Bytes>(Allocator.TempJob);
// Get a list of player names that have not been used
foreach (var name in Names)
{
if (!UsedNames.Contains(name.Name))
{
availablePlayerNames.Add(name.Name);
}
}
return availablePlayerNames;
}
}
#endregion
private NativeList<FixedString64Bytes> m_UsedNames;
private Random m_Random;
private EntityQuery m_ConnectedPlayers;
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<PlayerConnectedElement>();
state.RequireForUpdate<BotNameElement>();
m_UsedNames = new NativeList<FixedString64Bytes>(Allocator.Persistent);
var seed = DateTime.Now.Ticks / (DateTime.Now.Second + DateTime.Now.Day);
m_Random = new Random((uint)seed);
m_ConnectedPlayers = state.GetEntityQuery(ComponentType.ReadOnly<GhostOwner>());
state.RequireForUpdate<ReceiveRpcCommandRequest>();
state.RequireForUpdate<SetPlayerInfoRequest>();
UnityEngine.Debug.Log("SetPlayerInfoSystem has been loaded and initialized!");
}
//TODO : Optimize for DOTS?
public void OnUpdate(ref SystemState state)
{
var playersConnected = GetSingletonBuffer<PlayerConnectedElement>();
var commandBuffer = new EntityCommandBuffer(Allocator.TempJob);
var names = GetSingletonBuffer<BotNameElement>().ToNativeArray(Allocator.TempJob);
foreach (var (info, request, requestEntity) in
Query<SetPlayerInfoRequest, ReceiveRpcCommandRequest>().WithEntityAccess())
{
var entityNetwork = request.SourceConnection;
var networkId = GetComponent<NetworkId>(entityNetwork);
foreach (var (ghostOwner, entity) in Query<RefRO<GhostOwner>>()
.WithEntityAccess())
{
if (ghostOwner.ValueRO.NetworkId == networkId.Value)
{
var findANewNameJob = new FindAvailableNameJob
{
Names = names,
UsedNames = m_UsedNames,
Random = m_Random
};
state.Dependency = findANewNameJob.Schedule(state.Dependency);
state.Dependency.Complete();
// If the requester is not a client should use one from the bank of names.
var name = info.IsClient ? info.Name : m_UsedNames[m_UsedNames.Length - 1];
var playerID = info.PlayerId;
commandBuffer.SetComponent(entity, new PlayerName { Name = name });
commandBuffer.AddComponent(entity, new MultiversePlayerID { PlayerId = playerID });
playersConnected.Add(new PlayerConnectedElement { Name = name, PlayerId = playerID, Value = entity });
UnityEngine.Debug.Log($"Client: {name} ({playerID}) has joined the game! (Thin = {!info.IsClient})\nConnected Players: {m_ConnectedPlayers.CalculateEntityCount()}");
// If any players are connected, cancel the auto shutdown task
MultiverseSDKWrapper.Instance.CancelShutdown();
break;
}
}
commandBuffer.DestroyEntity(requestEntity);
}
commandBuffer.Playback(state.EntityManager);
}
}
}