Files
RobustToolbox/SS14.Client/Player/PlayerManager.cs
2017-05-20 22:26:34 +02:00

214 lines
7.8 KiB
C#

using Lidgren.Network;
using SFML.Window;
using SS14.Client.GameObjects;
using SS14.Client.Graphics.Render;
using SS14.Client.Interfaces.GOC;
using SS14.Client.Interfaces.Network;
using SS14.Client.Interfaces.Player;
using SS14.Client.Player.PostProcessing;
using SS14.Client.State.States;
using SS14.Shared;
using SS14.Shared.GameObjects;
using SS14.Shared.GameStates;
using SS14.Shared.GO;
using SS14.Shared.IoC;
using System;
using System.Collections.Generic;
using System.Linq;
namespace SS14.Client.Player
{
[IoCTarget]
public class PlayerManager : IPlayerManager
{
/* Here's the player controller. This will handle attaching GUIS and input to controllable things.
* Why not just attach the inputs directly? It's messy! This makes the whole thing nicely encapsulated.
* This class also communicates with the server to let the server control what entity it is attached to. */
private readonly List<PostProcessingEffect> _effects = new List<PostProcessingEffect>();
private readonly INetworkManager _networkManager;
private SessionStatus status = SessionStatus.Zombie;
public PlayerManager(INetworkManager networkManager)
{
_networkManager = networkManager;
}
#region IPlayerManager Members
public event EventHandler<TypeEventArgs> RequestedStateSwitch;
public event EventHandler<VectorEventArgs> OnPlayerMove;
public Entity ControlledEntity { get; private set; }
public void Update(float frameTime)
{
foreach (PostProcessingEffect e in _effects.ToArray())
{
e.Update(frameTime);
}
}
public void Attach(Entity newEntity)
{
// Detach and cleanup first
Detach();
ControlledEntity = newEntity;
ControlledEntity.AddComponent(ComponentFamily.Input,
IoCManager.Resolve<IEntityManagerContainer>().EntityManager.ComponentFactory.
GetComponent("KeyBindingInputComponent"));
ControlledEntity.AddComponent(ComponentFamily.Mover,
IoCManager.Resolve<IEntityManagerContainer>().EntityManager.ComponentFactory.
GetComponent("PlayerInputMoverComponent"));
ControlledEntity.AddComponent(ComponentFamily.Collider,
IoCManager.Resolve<IEntityManagerContainer>().EntityManager.ComponentFactory.
GetComponent("ColliderComponent"));
ControlledEntity.GetComponent<TransformComponent>(ComponentFamily.Transform).OnMove += PlayerEntityMoved;
}
public void ApplyEffects(RenderImage image)
{
foreach (PostProcessingEffect e in _effects)
{
e.ProcessImage(image);
}
}
public void Detach()
{
if (ControlledEntity != null && ControlledEntity.Initialized)
{
ControlledEntity.RemoveComponent(ComponentFamily.Input);
ControlledEntity.RemoveComponent(ComponentFamily.Mover);
ControlledEntity.RemoveComponent(ComponentFamily.Collider);
var transform = ControlledEntity.GetComponent<TransformComponent>(ComponentFamily.Transform);
if(transform != null)
transform.OnMove -= PlayerEntityMoved;
}
ControlledEntity = null;
}
public void KeyDown(Keyboard.Key key)
{
}
public void KeyUp(Keyboard.Key key)
{
}
public void ApplyPlayerStates(List<PlayerState> list)
{
PlayerState myState = list.FirstOrDefault(s => s.UniqueIdentifier == _networkManager.UniqueId);
if (myState == null)
return;
if (myState.ControlledEntity != null &&
(ControlledEntity == null ||
(ControlledEntity != null && myState.ControlledEntity != ControlledEntity.Uid)))
Attach(
IoCManager.Resolve<IEntityManagerContainer>().EntityManager.GetEntity((int) myState.ControlledEntity));
if (status != myState.Status)
SwitchState(myState.Status);
}
#endregion
#region netcode
public void HandleNetworkMessage(NetIncomingMessage message)
{
var messageType = (PlayerSessionMessage) message.ReadByte();
switch (messageType)
{
case PlayerSessionMessage.AttachToEntity:
//HandleAttachToEntity(message);
break;
case PlayerSessionMessage.JoinLobby:
/*if (RequestedStateSwitch != null)
{
RequestedStateSwitch(this, new TypeEventArgs(typeof(LobbyScreen)));
Detach();
}*/
break;
case PlayerSessionMessage.AddPostProcessingEffect:
var effectType = (PostProcessingEffectType) message.ReadInt32();
float duration = message.ReadFloat();
AddEffect(effectType, duration);
break;
}
}
/// <summary>
/// Verb sender
/// If UID is 0, it means its a global verb.
/// </summary>
/// <param name="verb">the verb</param>
/// <param name="uid">a target entity's Uid</param>
public void SendVerb(string verb, int uid)
{
NetOutgoingMessage message = _networkManager.CreateMessage();
message.Write((byte) NetMessage.PlayerSessionMessage);
message.Write((byte) PlayerSessionMessage.Verb);
message.Write(verb);
message.Write(uid);
_networkManager.SendMessage(message, NetDeliveryMethod.ReliableOrdered);
}
private void HandleAttachToEntity(NetIncomingMessage message)
{
int uid = message.ReadInt32();
Attach(IoCManager.Resolve<IEntityManagerContainer>().EntityManager.GetEntity(uid));
}
#endregion
public void AddEffect(PostProcessingEffectType type, float duration)
{
PostProcessingEffect e;
switch (type)
{
case PostProcessingEffectType.Blur:
e = new BlurPostProcessingEffect(duration);
e.OnExpired += EffectExpired;
_effects.Add(e);
break;
case PostProcessingEffectType.Death:
e = new DeathPostProcessingEffect(duration);
e.OnExpired += EffectExpired;
_effects.Add(e);
break;
//case PostProcessingEffectType.Acid:
// e = new AcidPostProcessingEffect(duration);
// e.OnExpired += EffectExpired;
// _effects.Add(e);
// break;
}
}
private void EffectExpired(PostProcessingEffect effect)
{
effect.OnExpired -= EffectExpired;
if (_effects.Contains(effect))
_effects.Remove(effect);
}
private void PlayerEntityMoved(object sender, VectorEventArgs args)
{
if (OnPlayerMove != null)
OnPlayerMove(sender, args);
}
private void SwitchState(SessionStatus newStatus)
{
status = newStatus;
if (status == SessionStatus.InLobby && RequestedStateSwitch != null)
{
RequestedStateSwitch(this, new TypeEventArgs(typeof (Lobby)));
Detach();
}
}
}
}