using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace SharedLibraryCore.Objects
{
public class Player : Database.Models.EFClient
{
public enum ClientState
{
///
/// represents when the client has been detected as joining
/// by the log file, but has not be authenticated by RCon
///
Connecting,
///
/// represents when the client has been parsed by RCon,
/// but has not been validated against the database
///
Authenticated,
///
/// represents when the client has been authenticated by RCon
/// and validated by the database
///
Connected,
///
/// represents when the client is leaving (either through RCon or log file)
///
Disconnecting,
}
public enum Permission
{
///
/// client has been banned
///
Banned = -1,
///
/// default client state upon first connect
///
User = 0,
///
/// client has been flagged
///
Flagged = 1,
///
/// client is trusted
///
Trusted = 2,
///
/// client is a moderator
///
Moderator = 3,
///
/// client is an administrator
///
Administrator = 4,
///
/// client is a senior administrator
///
SeniorAdmin = 5,
///
/// client is a owner
///
Owner = 6,
///
/// not used
///
Creator = 7,
///
/// reserved for default account
///
Console = 8
}
public Player()
{
ConnectionTime = DateTime.UtcNow;
ClientNumber = -1;
DelayedEvents = new Queue();
_additionalProperties = new Dictionary
{
{ "_reportCount", 0 }
};
}
public override string ToString() => $"{Name}::{NetworkId}";
///
/// send a message directly to the connected client
///
/// message content to send to client
public GameEvent Tell(String message)
{
var e = new GameEvent()
{
Message = message,
Target = this,
Owner = CurrentServer,
Type = GameEvent.EventType.Tell,
Data = message
};
this.CurrentServer?.Manager.GetEventHandler().AddEvent(e);
return e;
}
///
/// warn a client with given reason
///
/// reason for warn
/// client performing the warn
public GameEvent Warn(String warnReason, Player sender)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.Warn,
Message = warnReason,
Data = warnReason,
Origin = sender,
Target = this,
Owner = sender.CurrentServer
};
// enforce level restrictions
if (this.Level > sender.Level)
{
e.FailReason = GameEvent.EventFailReason.Permission;
}
else
{
this.Warnings++;
}
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
return e;
}
///
/// clear all warnings for a client
///
/// client performing the warn clear
///
public GameEvent WarnClear(Player sender)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.WarnClear,
Origin = sender,
Target = this,
Owner = sender.CurrentServer
};
// enforce level restrictions
if (sender.Level <= this.Level)
{
e.FailReason = GameEvent.EventFailReason.Permission;
return e;
}
this.Warnings = 0;
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
return e;
}
///
/// report a client for a given reason
///
/// reason for the report
/// client performing the report
///
public GameEvent Report(string reportReason, Player sender)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.Report,
Message = reportReason,
Data = reportReason,
Origin = sender,
Target = this,
Owner = sender.CurrentServer
};
int reportCount = sender.GetAdditionalProperty("_reportCount");
if (this.Level > sender.Level)
{
e.FailReason = GameEvent.EventFailReason.Permission;
}
else if (this.Equals(sender))
{
e.FailReason = GameEvent.EventFailReason.Invalid;
}
else if (reportCount > 2)
{
e.FailReason = GameEvent.EventFailReason.Throttle;
}
else if (CurrentServer.Reports.Count(report => (report.Origin.NetworkId == sender.NetworkId &&
report.Target.NetworkId == this.NetworkId)) > 0)
{
e.FailReason = GameEvent.EventFailReason.Exception;
}
sender.SetAdditionalProperty("_reportCount", reportCount + 1);
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
return e;
}
///
/// flag a client for a given reason
///
/// reason for flagging
/// client performing the flag
/// game event for the flag
public GameEvent Flag(string flagReason, Player sender)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.Flag,
Origin = sender,
Data = flagReason,
Message = flagReason,
Target = this,
Owner = sender.CurrentServer
};
if (this.Level >= sender.Level)
{
e.FailReason = GameEvent.EventFailReason.Permission;
}
else if (this.Level == Player.Permission.Flagged)
{
e.FailReason = GameEvent.EventFailReason.Invalid;
}
else
{
this.Level = Player.Permission.Flagged;
}
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
return e;
}
///
/// unflag a client for a given reason
///
/// reason to unflag a player for
/// client performing the unflag
/// game event for the un flug
public GameEvent Unflag(string unflagReason, Player sender)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.Unflag,
Origin = sender,
Target = this,
Data = unflagReason,
Message = unflagReason,
Owner = sender.CurrentServer
};
if (sender.Level <= this.Level)
{
e.FailReason = GameEvent.EventFailReason.Permission;
}
else if (this.Level != Player.Permission.Flagged)
{
e.FailReason = GameEvent.EventFailReason.Invalid;
}
else
{
this.Level = Permission.User;
}
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
return e;
}
///
/// kick a client for the given reason
///
/// reason to kick for
/// client performing the kick
public GameEvent Kick(String kickReason, Player sender)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.Kick,
Message = kickReason,
Target = this,
Origin = sender,
Data = kickReason,
Owner = sender.CurrentServer
};
// enforce level restrictions
if (this.Level > sender.Level)
{
e.FailReason = GameEvent.EventFailReason.Permission;
}
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
return e;
}
///
/// temporarily ban a client for the given time span
///
/// reason for the temp ban
/// how long the temp ban lasts
/// client performing the tempban
public GameEvent TempBan(String tempbanReason, TimeSpan banLength, Player sender)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.TempBan,
Message = tempbanReason,
Data = tempbanReason,
Origin = sender,
Target = this,
Extra = banLength,
Owner = sender.CurrentServer
};
// enforce level restrictions
if (sender.Level <= this.Level)
{
e.FailReason = GameEvent.EventFailReason.Permission;
}
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
return e;
}
///
/// permanently ban a client
///
/// reason for the ban
/// client performing the ban
public GameEvent Ban(String banReason, Player sender)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.Ban,
Message = banReason,
Data = banReason,
Origin = sender,
Target = this,
Owner = sender.CurrentServer
};
// enforce level restrictions
if (sender.Level <= this.Level)
{
e.FailReason = GameEvent.EventFailReason.Permission;
}
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
return e;
}
///
/// unban a client
///
/// reason for the unban
/// client performing the unban
///
public GameEvent Unban(String unbanReason, Player sender)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.Unban,
Message = unbanReason,
Data = unbanReason,
Origin = sender,
Target = this,
Owner = sender.CurrentServer
};
// enforce level restrictions
if (this.Level > sender.Level)
{
e.FailReason = GameEvent.EventFailReason.Permission;
}
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
return e;
}
[NotMapped]
Dictionary _additionalProperties;
public T GetAdditionalProperty(string name) => (T)_additionalProperties[name];
public void SetAdditionalProperty(string name, object value)
{
if (_additionalProperties.ContainsKey(name))
{
_additionalProperties[name] = value;
}
else
{
_additionalProperties.Add(name, value);
}
}
[NotMapped]
public int ClientNumber { get; set; }
[NotMapped]
public int Ping { get; set; }
[NotMapped]
public int Warnings { get; set; }
[NotMapped]
public DateTime ConnectionTime { get; set; }
[NotMapped]
public int ConnectionLength => (int)(DateTime.UtcNow - ConnectionTime).TotalSeconds;
[NotMapped]
public Server CurrentServer { get; set; }
[NotMapped]
public int Score { get; set; }
[NotMapped]
public bool IsBot { get; set; }
private int _ipaddress;
public override int IPAddress
{
get { return _ipaddress; }
set { _ipaddress = value; }
}
private string _name;
public override string Name
{
get { return _name; }
set { _name = value; }
}
[NotMapped]
public ClientState State { get; set; }
[NotMapped]
public Queue DelayedEvents { get; set; }
[NotMapped]
// this is kinda dirty, but I need localizable level names
public ClientPermission ClientPermission => new ClientPermission()
{
Level = Level,
Name = Utilities.CurrentLocalization
.LocalizationIndex[$"GLOBAL_PERMISSION_{Level.ToString().ToUpper()}"]
};
public override bool Equals(object obj)
{
return ((Player)obj).NetworkId == this.NetworkId;
}
public override int GetHashCode() => (int)NetworkId;
}
}