-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Expand file tree
/
Copy pathLocalPlayer.cs
More file actions
150 lines (127 loc) · 5.56 KB
/
LocalPlayer.cs
File metadata and controls
150 lines (127 loc) · 5.56 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using System;
using NitroxClient.Communication.Abstract;
using NitroxClient.GameLogic.PlayerLogic.PlayerModel;
using NitroxClient.GameLogic.PlayerLogic.PlayerModel.Abstract;
using NitroxClient.MonoBehaviours;
using NitroxClient.Unity.Helper;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.GameLogic;
using NitroxModel.DataStructures.Util;
using NitroxModel.MultiplayerSession;
using NitroxModel.Packets;
using NitroxModel_Subnautica.DataStructures;
using UnityEngine;
using UnityEngine.Rendering;
using Object = UnityEngine.Object;
namespace NitroxClient.GameLogic;
public class LocalPlayer : ILocalNitroxPlayer
{
private readonly IMultiplayerSession multiplayerSession;
private readonly IPacketSender packetSender;
private readonly ThrottledPacketSender throttledPacketSender;
private readonly Lazy<GameObject> body;
private readonly Lazy<GameObject> playerModel;
private readonly Lazy<GameObject> bodyPrototype;
public GameObject Body => body.Value;
public GameObject PlayerModel => playerModel.Value;
public GameObject BodyPrototype => bodyPrototype.Value;
public string PlayerName => multiplayerSession.AuthenticationContext.Username;
/// <summary>
/// Gets the player id. The session is lost on disconnect so this can return null.
/// </summary>
public ushort? PlayerId => multiplayerSession?.Reservation?.PlayerId;
public PlayerSettings PlayerSettings => multiplayerSession.PlayerSettings;
public Perms Permissions { get; set; }
public IntroCinematicMode IntroCinematicMode { get; set; }
public bool KeepInventoryOnDeath { get; set; }
public bool MarkDeathPointsWithBeacon { get; set; }
public LocalPlayer(IMultiplayerSession multiplayerSession, IPacketSender packetSender, ThrottledPacketSender throttledPacketSender)
{
this.multiplayerSession = multiplayerSession;
this.packetSender = packetSender;
this.throttledPacketSender = throttledPacketSender;
body = new Lazy<GameObject>(() => Player.main.RequireGameObject("body"));
playerModel = new Lazy<GameObject>(() => Body.RequireGameObject("player_view"));
bodyPrototype = new Lazy<GameObject>(CreateBodyPrototype);
Permissions = Perms.PLAYER;
IntroCinematicMode = IntroCinematicMode.NONE;
KeepInventoryOnDeath = false;
MarkDeathPointsWithBeacon = false;
}
public void BroadcastLocation(Vector3 location, Vector3 velocity, Quaternion bodyRotation, Quaternion aimingRotation)
{
if (!PlayerId.HasValue)
{
return;
}
PlayerMovement playerMovement = new(PlayerId.Value, location.ToDto(), velocity.ToDto(), bodyRotation.ToDto(), aimingRotation.ToDto());
packetSender.Send(playerMovement);
}
public void AnimationChange(AnimChangeType type, AnimChangeState state)
{
if (PlayerId.HasValue)
{
packetSender.Send(new AnimationChangeEvent(PlayerId.Value, (int)type, (int)state));
}
}
public void BroadcastStats(float oxygen, float maxOxygen, float health, float food, float water, float infectionAmount)
{
if (PlayerId.HasValue)
{
packetSender.Send(new PlayerStats(PlayerId.Value, oxygen, maxOxygen, health, food, water, infectionAmount));
}
}
public void BroadcastDeath(Vector3 deathPosition)
{
if (PlayerId.HasValue)
{
packetSender.Send(new PlayerDeathEvent(PlayerId.Value, deathPosition.ToDto()));
if (MarkDeathPointsWithBeacon)
{
DeathBeacon.SpawnDeathBeacon(deathPosition.ToDto(), PlayerName);
}
}
}
public void BroadcastSubrootChange(Optional<NitroxId> subrootId)
{
if (PlayerId.HasValue)
{
packetSender.Send(new SubRootChanged(PlayerId.Value, subrootId));
}
}
public void BroadcastEscapePodChange(Optional<NitroxId> escapePodId)
{
if (PlayerId.HasValue)
{
packetSender.Send(new EscapePodChanged(PlayerId.Value, escapePodId));
}
}
public void BroadcastWeld(NitroxId id, float healthAdded) => packetSender.Send(new WeldAction(id, healthAdded));
public void BroadcastHeldItemChanged(NitroxId itemId, PlayerHeldItemChanged.ChangeType techType, NitroxTechType isFirstTime)
{
if (PlayerId.HasValue)
{
packetSender.Send(new PlayerHeldItemChanged(PlayerId.Value, itemId, techType, isFirstTime));
}
}
public void BroadcastQuickSlotsBindingChanged(Optional<NitroxId>[] slotItemIds) => throttledPacketSender.SendThrottled(new PlayerQuickSlotsBindingChanged(slotItemIds), (packet) => 1);
private GameObject CreateBodyPrototype()
{
GameObject prototype = Body;
// Cheap fix for showing head, much easier since male_geo contains many different heads
prototype.GetComponentInParent<Player>().head.shadowCastingMode = ShadowCastingMode.On;
GameObject clone = Object.Instantiate(prototype, Multiplayer.Main.transform, false);
prototype.GetComponentInParent<Player>().head.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
clone.SetActive(false);
clone.name = "RemotePlayerPrototype";
// Removing items that are held in hand
foreach (Transform child in clone.transform.Find($"player_view/{PlayerEquipmentConstants.ITEM_ATTACH_POINT_GAME_OBJECT_NAME}"))
{
if (!child.gameObject.name.Contains("attach1_"))
{
Object.DestroyImmediate(child.gameObject);
}
}
return clone;
}
}