-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Expand file tree
/
Copy pathPlayerJoiningMultiplayerSessionProcessor.cs
More file actions
123 lines (109 loc) · 5.48 KB
/
PlayerJoiningMultiplayerSessionProcessor.cs
File metadata and controls
123 lines (109 loc) · 5.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
using System.Collections.Generic;
using System.Linq;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.GameLogic;
using NitroxModel.DataStructures.GameLogic.Entities;
using NitroxModel.DataStructures.Unity;
using NitroxModel.DataStructures.Util;
using NitroxModel.Helper;
using NitroxModel.MultiplayerSession;
using NitroxModel.Networking;
using NitroxModel.Packets;
using NitroxModel.Serialization;
using NitroxServer.Communication.Packets.Processors.Abstract;
using NitroxServer.GameLogic;
using NitroxServer.GameLogic.Bases;
using NitroxServer.GameLogic.Entities;
using NitroxServer.Serialization;
using NitroxServer.Serialization.World;
namespace NitroxServer.Communication.Packets.Processors
{
public class PlayerJoiningMultiplayerSessionProcessor : UnauthenticatedPacketProcessor<PlayerJoiningMultiplayerSession>
{
private readonly PlayerManager playerManager;
private readonly ScheduleKeeper scheduleKeeper;
private readonly StoryManager storyManager;
private readonly World world;
private readonly EntityRegistry entityRegistry;
private readonly SubnauticaServerConfig serverConfig;
private readonly NtpSyncer ntpSyncer;
public PlayerJoiningMultiplayerSessionProcessor(ScheduleKeeper scheduleKeeper, StoryManager storyManager, PlayerManager playerManager, World world, EntityRegistry entityRegistry, SubnauticaServerConfig serverConfig, NtpSyncer ntpSyncer)
{
this.scheduleKeeper = scheduleKeeper;
this.storyManager = storyManager;
this.playerManager = playerManager;
this.world = world;
this.entityRegistry = entityRegistry;
this.serverConfig = serverConfig;
this.ntpSyncer = ntpSyncer;
}
public override void Process(PlayerJoiningMultiplayerSession packet, INitroxConnection connection)
{
Player player = playerManager.PlayerConnected(connection, packet.ReservationKey, out bool wasBrandNewPlayer);
NitroxId assignedEscapePodId = world.EscapePodManager.AssignPlayerToEscapePod(player.Id, out Optional<EscapePodWorldEntity> newlyCreatedEscapePod);
if (newlyCreatedEscapePod.HasValue)
{
SpawnEntities spawnNewEscapePod = new(newlyCreatedEscapePod.Value);
playerManager.SendPacketToOtherPlayers(spawnNewEscapePod, player);
}
// Make players on localhost admin by default.
if (connection.Endpoint.Address.IsLocalhost())
{
Log.Info($"Granted admin to '{player.Name}' because they're playing on the host machine");
player.Permissions = Perms.ADMIN;
}
List<SimulatedEntity> simulations = world.EntitySimulation.AssignGlobalRootEntitiesAndGetData(player);
player.Entity = wasBrandNewPlayer ? SetupPlayerEntity(player) : RespawnExistingEntity(player);
List<GlobalRootEntity> globalRootEntities = world.WorldEntityManager.GetGlobalRootEntities(true);
bool isFirstPlayer = playerManager.GetConnectedPlayers().Count == 1;
InitialPlayerSync initialPlayerSync = new(player.GameObjectId,
wasBrandNewPlayer,
assignedEscapePodId,
player.EquippedItems,
player.UsedItems,
player.QuickSlotsBindingIds,
world.GameData.PDAState.GetInitialPDAData(),
world.GameData.StoryGoals.GetInitialStoryGoalData(scheduleKeeper, player),
player.Position,
player.Rotation,
player.SubRootId,
player.Stats,
GetOtherPlayers(player),
globalRootEntities,
simulations,
player.GameMode,
player.Permissions,
wasBrandNewPlayer ? IntroCinematicMode.LOADING : IntroCinematicMode.COMPLETED,
new(new(player.PingInstancePreferences), player.PinnedRecipePreferences.ToList()),
storyManager.GetTimeData(),
isFirstPlayer,
BuildingManager.GetEntitiesOperations(globalRootEntities),
serverConfig.KeepInventoryOnDeath,
serverConfig.MarkDeathPointsWithBeacon
);
player.SendPacket(initialPlayerSync);
}
private IEnumerable<PlayerContext> GetOtherPlayers(Player player)
{
return playerManager.GetConnectedPlayers().Where(p => p != player)
.Select(p => p.PlayerContext);
}
private PlayerWorldEntity SetupPlayerEntity(Player player)
{
NitroxTransform transform = new(player.Position, player.Rotation, NitroxVector3.One);
PlayerWorldEntity playerEntity = new PlayerWorldEntity(transform, 0, null, false, player.GameObjectId, NitroxTechType.None, null, null, new List<Entity>());
entityRegistry.AddOrUpdate(playerEntity);
world.WorldEntityManager.TrackEntityInTheWorld(playerEntity);
return playerEntity;
}
private PlayerWorldEntity RespawnExistingEntity(Player player)
{
if (entityRegistry.TryGetEntityById(player.PlayerContext.PlayerNitroxId, out PlayerWorldEntity playerWorldEntity))
{
return playerWorldEntity;
}
Log.Error($"Unable to find player entity for {player.Name}. Re-creating one");
return SetupPlayerEntity(player);
}
}
}