no message

This commit is contained in:
SilicaAndPina 2020-10-03 03:30:31 +13:00
parent 28306365d1
commit 076da115c6
15 changed files with 637 additions and 107 deletions

View file

@ -78,7 +78,7 @@ namespace Horse_Isle_Server
}
else
{
if (message.ToLower().Contains(filter.FilteredWord.ToLower()))
if (message.ToLower().Contains(filter.FilteredWord))
return filter.Reason;
}
}
@ -106,7 +106,21 @@ namespace Horse_Isle_Server
}
}
public static Client[] GetRecipiants(User user, ChatChannel channel)
public static string GetDmRecipiant(string message)
{
if(message.Contains('|'))
{
string recipiantName = message.Split('|')[0];
return recipiantName.Substring(2);
}
else
{
return null;
}
}
public static Client[] GetRecipiants(User user, ChatChannel channel, string to=null)
{
if (channel == ChatChannel.All)
{
@ -187,6 +201,27 @@ namespace Horse_Isle_Server
return recipiants.ToArray();
}
if(channel == ChatChannel.Dm)
{
if (to != null)
{
List<Client> recipiants = new List<Client>();
foreach (Client client in Server.ConnectedClients)
{
if (client.LoggedIn)
if (!client.LoggedinUser.MutePrivateMessage)
if (client.LoggedinUser.Username != to)
recipiants.Add(client);
}
return recipiants.ToArray();
}
else
{
Logger.ErrorPrint("Channel is " + channel + " (DM) BUT no 'to' Paramater was specfied");
return new Client[0];
}
}
Logger.ErrorPrint(user.Username + " Sent message in unknown channel: " + (byte)channel);
return new Client[0]; // No recipiants
@ -241,7 +276,6 @@ namespace Horse_Isle_Server
return "not implemented yet :(";
}
}
public static string FormatChatForSender(User user, ChatChannel channel, string message)
{
switch (channel)
@ -264,6 +298,32 @@ namespace Horse_Isle_Server
return "not implemented yet :(";
}
}
public static string NonViolationChecks(User user, string message)
{
// Check if contains password.
if (message.ToLower().Contains(user.Password.ToLower()))
{
return Messages.PasswordNotice;
}
// Check if ALL CAPS
if (message.Contains(' ')) // hi1 apparently doesnt care about caps if its all 1 word?
{
string[] wordsSaid = message.Split(' ');
foreach (string word in wordsSaid)
{
if (word.ToUpper() == word)
{
return Messages.CapsNotice;
}
}
}
return null;
}
public static Reason GetReason(string name)
{
foreach (Reason reason in Reasons)

View file

@ -14,22 +14,52 @@ namespace Horse_Isle_Server
public User LoggedinUser;
private Thread recvPackets;
private Timer updateTimer;
private Timer inactivityTimer;
private Timer warnTimer;
private Timer kickTimer;
private int keepAliveInterval = 60 * 1000;
private int updateInterval = 60 * 1000;
private int warnInterval = Server.IdleWarning * 60 * 1000;
private int kickInterval = Server.IdleTimeout * 60 * 1000;
private void keepAliveTimerTick(object state)
{
Logger.DebugPrint("Sending keep-alive packet to "+ LoggedinUser.Username);
byte[] updatePacket = PacketBuilder.CreateKeepAlive();
SendPacket(updatePacket);
}
private void warnTimerTick(object state)
{
Logger.DebugPrint("Sending inactivity warning to: " + RemoteIp);
byte[] chatPacket = PacketBuilder.CreateChat(Messages.FormatIdleWarningMessage(), PacketBuilder.CHAT_BOTTOM_RIGHT);
SendPacket(chatPacket);
}
private void kickTimerTick(object state)
{
Kick(Messages.FormatIdleKickMessage());
}
private void updateTimerTick(object state)
{
Logger.DebugPrint("Sending update packet to "+ LoggedinUser.Username);
byte[] updatePacket = PacketBuilder.CreateUpdate();
SendPacket(updatePacket);
Server.UpdateArea(this);
Server.UpdateWorld(this);
Server.UpdatePlayer(this);
}
public void Login(int id)
{
LoggedinUser = new User(id);
LoggedIn = true;
updateTimer = new Timer(new TimerCallback(updateTimerTick), null, updateInterval, updateInterval);
inactivityTimer = new Timer(new TimerCallback(keepAliveTimerTick), null, keepAliveInterval, keepAliveInterval);
}
private void receivePackets()
{
@ -54,6 +84,7 @@ namespace Horse_Isle_Server
ms.Seek(0x00, SeekOrigin.Begin);
byte[] fullPacket = ms.ToArray();
parsePackets(fullPacket);
ms.Close();
ms = new MemoryStream();
}
@ -63,7 +94,7 @@ namespace Horse_Isle_Server
}
catch(SocketException e)
{
Logger.ErrorPrint("Socket exception occured: " + e.Message +" and so it was disconnected.");
Logger.ErrorPrint("Socket exception occured: " + e.Message);
Disconnect();
break;
}
@ -81,8 +112,16 @@ namespace Horse_Isle_Server
}
byte identifier = Packet[0];
if (updateTimer != null)
updateTimer.Change(updateInterval, updateInterval);
// Reset timers
if (inactivityTimer != null && identifier != PacketBuilder.PACKET_KEEP_ALIVE)
inactivityTimer.Change(keepAliveInterval, keepAliveInterval);
if (kickTimer != null && identifier != PacketBuilder.PACKET_KEEP_ALIVE)
kickTimer.Change(kickInterval, kickInterval);
if (warnTimer != null && identifier != PacketBuilder.PACKET_KEEP_ALIVE)
warnTimer.Change(warnInterval, warnInterval);
if (!LoggedIn) // Must be either login or policy-file-request
{
@ -113,8 +152,8 @@ namespace Horse_Isle_Server
case PacketBuilder.PACKET_CHAT:
Server.OnChatPacket(this, Packet);
break;
case PacketBuilder.PACKET_UPDATE:
Server.OnUpdatePacket(this, Packet);
case PacketBuilder.PACKET_KEEP_ALIVE:
Server.OnKeepAlive(this, Packet);
break;
default:
Logger.ErrorPrint("Unimplemented Packet: " + BitConverter.ToString(Packet).Replace('-', ' '));
@ -127,14 +166,31 @@ namespace Horse_Isle_Server
{
Logger.DebugPrint(ClientSocket.RemoteEndPoint + " has Disconnected.");
recvPackets.Abort();
updateTimer.Dispose();
if(updateTimer != null)
updateTimer.Dispose();
if(inactivityTimer != null)
inactivityTimer.Dispose();
if(warnTimer != null)
warnTimer.Dispose();
if(kickTimer != null)
kickTimer.Dispose();
Server.OnDisconnect(this);
LoggedIn = false;
LoggedinUser = null;
Server.ConnectedClients.Remove(this);
ClientSocket.Close();
ClientSocket.Dispose();
}
public void Kick(string Reason)
{
byte[] kickPacket = PacketBuilder.CreateKickMessage(Reason);
SendPacket(kickPacket);
Disconnect();
Logger.InfoPrint("CLIENT: "+RemoteIp+" KICKED for: "+Reason);
}
public void SendPacket(byte[] PacketData)
{
try
@ -143,7 +199,7 @@ namespace Horse_Isle_Server
}
catch (SocketException e)
{
Logger.ErrorPrint("Socket exception occured: " + e.Message + " and so it was disconnected.");
Logger.ErrorPrint("Socket exception occured: " + e.Message);
Disconnect();
}
}
@ -155,6 +211,9 @@ namespace Horse_Isle_Server
Logger.DebugPrint("Client connected @ " + RemoteIp);
kickTimer = new Timer(new TimerCallback(kickTimerTick), null, kickInterval, kickInterval);
warnTimer = new Timer(new TimerCallback(warnTimerTick), null, warnInterval, warnInterval);
recvPackets = new Thread(() =>
{
receivePackets();

View file

@ -17,7 +17,7 @@ namespace Horse_Isle_Server
string ExtTable = "CREATE TABLE UserExt(Id INT, X INT, Y INT, Money INT, BankBalance BIGINT,ProfilePage Text(1028), CharId INT, ChatViolations INT)";
string MailTable = "CREATE TABLE Mailbox(IdTo INT, PlayerFrom TEXT(16),Subject TEXT(128), Message Text(1028), TimeSent INT)";
string BuddyTable = "CREATE TABLE BuddyList(Id INT, IdFriend INT, Pending BOOL)";
string WorldTable = "CREATE TABLE World(TimeStarted INT, Weather TEXT(64))";
string WorldTable = "CREATE TABLE World(Time INT,Day INT, Year INT, Weather TEXT(64))";
string DroppedTable = "CREATE TABLE DroppedItems(X INT, Y INT, ItemID INT)";
try
@ -87,11 +87,9 @@ namespace Horse_Isle_Server
sqlCommand.ExecuteNonQuery();
int epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
sqlCommand = db.CreateCommand();
sqlCommand.CommandText = "INSERT INTO World VALUES(@unix,'SUNNY')";
sqlCommand.Parameters.AddWithValue("@unix", epoch);
sqlCommand.CommandText = "INSERT INTO World VALUES(0,0,0,'SUNNY')";
sqlCommand.Prepare();
sqlCommand.ExecuteNonQuery();
@ -103,14 +101,40 @@ namespace Horse_Isle_Server
}
public static int GetServerCreationTime()
public static void SetServerTime(int time, int day, int year)
{
MySqlCommand sqlCommand = db.CreateCommand();
sqlCommand.CommandText = "SELECT TimeStarted FROM World";
sqlCommand.CommandText = "UPDATE World SET Time=@time,Day=@day,Year=@year";
sqlCommand.Parameters.AddWithValue("@time", time);
sqlCommand.Parameters.AddWithValue("@day", day);
sqlCommand.Parameters.AddWithValue("@year", year);
sqlCommand.Prepare();
sqlCommand.ExecuteNonQuery();
}
public static int GetServerTime()
{
MySqlCommand sqlCommand = db.CreateCommand();
sqlCommand.CommandText = "SELECT Time FROM World";
int serverTime = Convert.ToInt32(sqlCommand.ExecuteScalar());
return serverTime;
}
public static int GetServerDay()
{
MySqlCommand sqlCommand = db.CreateCommand();
sqlCommand.CommandText = "SELECT Day FROM World";
int serverTime = Convert.ToInt32(sqlCommand.ExecuteScalar());
return serverTime;
}
public static int GetServerYear()
{
MySqlCommand sqlCommand = db.CreateCommand();
sqlCommand.CommandText = "SELECT Year FROM World";
int creationTime = Convert.ToInt32(sqlCommand.ExecuteScalar());
return creationTime;
}
public static string GetWorldWeather()
{
MySqlCommand sqlCommand = db.CreateCommand();

View file

@ -117,9 +117,11 @@ namespace Horse_Isle_Server
// Announcements
Messages.LoginFormat = gameData.messages.login_format;
Messages.WelcomeFormat = gameData.messages.welcome_format;
Messages.MotdFormat = gameData.messages.motd_format;
Messages.ProfileSavedMessage = gameData.messages.profile_save;
Messages.LoginMessageForamt = gameData.messages.login_format;
Messages.LogoutMessageFormat = gameData.messages.logout_format;
// Chat
@ -144,6 +146,9 @@ namespace Horse_Isle_Server
Messages.ModChatFormatForSender = gameData.messages.chat.for_sender.mod_format;
Messages.AdminChatFormatForSender = gameData.messages.chat.for_sender.admin_format;
Messages.PasswordNotice = gameData.messages.chat.password_included;
Messages.CapsNotice = gameData.messages.chat.caps_notice;
// Meta Format
Messages.LocationFormat = gameData.messages.meta.location_format;
@ -159,6 +164,17 @@ namespace Horse_Isle_Server
Map.OverlayTileDepth = gameData.tile_paramaters.overlay_tiles.tile_depth.ToObject<int[]>();
Map.OverlayTilesetPassibility = gameData.tile_paramaters.overlay_tiles.passibility.ToObject<bool[][]>();
Map.TerrainTilePassibility = gameData.tile_paramaters.terrain_tiles.passibility.ToObject<bool[]>();
// Disconnect Reasons
Messages.BanMessage = gameData.messages.disconnect.banned;
Messages.IdleKickMessageFormat = gameData.messages.disconnect.client_timeout.kick_message;
Messages.IdleWarningFormat = gameData.messages.disconnect.client_timeout.warn_message;
Server.IdleWarning = gameData.messages.disconnect.client_timeout.warn_after;
Server.IdleTimeout = gameData.messages.disconnect.client_timeout.kick_after;
}
}

View file

@ -21,5 +21,9 @@ namespace Horse_Isle_Server
{
Console.WriteLine("[ERROR] " + text);
}
public static void InfoPrint(string text)
{
Console.WriteLine("[INFO] " + text);
}
}
}

View file

@ -10,9 +10,11 @@ namespace Horse_Isle_Server
{
// Announcements
public static string NewUserMessage;
public static string LoginFormat;
public static string WelcomeFormat;
public static string MotdFormat;
public static string IdleWarningFormat;
public static string LoginMessageForamt;
public static string LogoutMessageFormat;
// Records
public static string ProfileSavedMessage;
@ -38,6 +40,8 @@ namespace Horse_Isle_Server
public static string ChatViolationMessageFormat;
public static int RequiredChatViolations;
public static string PasswordNotice;
public static string CapsNotice;
// Meta
public static string IsleFormat;
@ -49,6 +53,10 @@ namespace Horse_Isle_Server
public static string NothingMessage;
public static string Seperator;
// Disconnect Messages
public static string BanMessage;
public static string IdleKickMessageFormat;
public static string FormatGlobalChatViolationMessage(Chat.Reason violationReason)
{
return ChatViolationMessageFormat.Replace("%AMOUNT%", RequiredChatViolations.ToString()).Replace("%REASON%", violationReason.Message);
@ -114,25 +122,36 @@ namespace Horse_Isle_Server
{
return DirectChatFormatForSender.Replace("%FROMUSER%", username).Replace("%TOUSER%", toUsername).Replace(" %MESSAGE%", message);
}
public static string FormatIdleWarningMessage()
{
return IdleWarningFormat.Replace("%WARN%", Server.IdleWarning.ToString()).Replace("%KICK%", Server.IdleTimeout.ToString());
}
public static string FormatLoginMessage(string username)
{
return LoginMessageForamt.Replace("%USERNAME%", username);
}
public static string FormatLogoutMessage(string username)
{
return LogoutMessageFormat.Replace("%USERNAME%", username);
}
public static string FormatMOTD()
{
return MotdFormat.Replace("%MOTD%", ConfigReader.Motd);
}
public static string FormatLoginMessage(string username)
public static string FormatWelcomeMessage(string username)
{
return LoginFormat.Replace("%USERNAME%", username);
return WelcomeFormat.Replace("%USERNAME%", username);
}
// Disconnect
public static string FormatIdleKickMessage()
{
return IdleKickMessageFormat.Replace("%KICK%", Server.IdleTimeout.ToString());
}
// Meta
public static string FormatLocationData(int x, int y)
{
string locationString = "";

View file

@ -8,7 +8,7 @@ namespace Horse_Isle_Server
{
public const byte PACKET_TERMINATOR = 0x00;
public const byte PACKET_A_TERMINATOR = 0x0A;
public const byte PACKET_CLIENT_TERMINATOR = 0x0A;
public const byte PACKET_LOGIN = 0x7F;
@ -21,8 +21,15 @@ namespace Horse_Isle_Server
public const byte PACKET_AREA_DEFS = 0x79;
public const byte PACKET_ANNOUNCEMENT = 0x7E;
public const byte PACKET_TILE_FLAGS = 0x75;
public const byte PACKET_UPDATE = 0x7C;
public const byte PACKET_KEEP_ALIVE = 0x7C;
public const byte PACKET_PROFILE = 0x18;
public const byte PACKET_KICK = 0x80;
public const byte PACKET_LEAVE = 0x7D;
public const byte PACKET_PLAYERINFO = 0x16;
public const byte PLAYERINFO_LEAVE = 0x16;
public const byte PLAYERINFO_UPDATE_OR_CREATE = 0x15;
public const byte VIEW_PROFILE = 0x14;
public const byte SAVE_PROFILE = 0x15;
@ -49,10 +56,58 @@ namespace Horse_Isle_Server
public const byte DIRECTION_RIGHT = 1;
public const byte DIRECTION_DOWN = 2;
public const byte DIRECTION_LEFT = 3;
public const byte DIRECTION_LOGIN = 4;
public const byte DIRECTION_TELEPORT = 4;
public const byte DIRECTION_NONE = 10;
public static byte[] CreatePlayerLeavePacket(string username)
{
MemoryStream ms = new MemoryStream();
ms.WriteByte(PACKET_PLAYERINFO);
ms.WriteByte(PLAYERINFO_LEAVE);
byte[] strBytes = Encoding.UTF8.GetBytes(username);
ms.Write(strBytes, 0x00, strBytes.Length);
ms.WriteByte(PACKET_TERMINATOR);
ms.Seek(0x00, SeekOrigin.Begin);
byte[] Packet = ms.ToArray();
ms.Dispose();
return Packet;
}
public static byte[] CreatePlayerInfoUpdateOrCreate(int x, int y, int facing, int charId, string username)
{
MemoryStream ms = new MemoryStream();
ms.WriteByte(PACKET_PLAYERINFO);
ms.WriteByte(PLAYERINFO_UPDATE_OR_CREATE);
ms.WriteByte((byte)(((x - 4) / 64) + 20));
ms.WriteByte((byte)(((x - 4) % 64) + 20));
ms.WriteByte((byte)(((y - 1) / 64) + 20));
ms.WriteByte((byte)(((y - 1) % 64) + 20));
ms.WriteByte((byte)(facing + 20));
ms.WriteByte((byte)((charId / 64) + 20)); //6
ms.WriteByte((byte)((charId % 64) + 20)); //7
byte[] strBytes = Encoding.UTF8.GetBytes(username);
ms.Write(strBytes, 0x00, strBytes.Length);
ms.WriteByte(PACKET_TERMINATOR);
ms.Seek(0x00, SeekOrigin.Begin);
byte[] Packet = ms.ToArray();
ms.Dispose();
return Packet;
}
public static byte[] CreateLoginPacket(bool Success)
{
@ -215,7 +270,7 @@ namespace Horse_Isle_Server
ms.WriteByte((byte)otileId);
}
}
if (direction == DIRECTION_LOGIN)
if (direction == DIRECTION_TELEPORT)
{
for(int rely = 0; rely <= 9; rely++)
{
@ -262,7 +317,7 @@ namespace Horse_Isle_Server
ms.WriteByte(PACKET_PLACE_INFO);
ms.Write(strBytes, 0x00, strBytes.Length);
ms.WriteByte(PACKET_TERMINATOR);
ms.Seek(0x00, SeekOrigin.Begin);
@ -317,11 +372,11 @@ namespace Horse_Isle_Server
return Packet;
}
public static byte[] CreateUpdate()
public static byte[] CreateKeepAlive()
{
MemoryStream ms = new MemoryStream();
ms.WriteByte(PACKET_UPDATE);
ms.WriteByte(PACKET_KEEP_ALIVE);
ms.WriteByte(PACKET_TERMINATOR);
ms.Seek(0x00, SeekOrigin.Begin);
@ -419,7 +474,7 @@ namespace Horse_Isle_Server
return Packet;
}
public static byte[] CreateBaseStats(int money, int playerCount, int mail)
public static byte[] CreatePlayerData(int money, int playerCount, int mail)
{
byte[] moneyStrBytes = Encoding.UTF8.GetBytes(money.ToString());
byte[] playerStrBytes = Encoding.UTF8.GetBytes(playerCount.ToString());
@ -460,6 +515,7 @@ namespace Horse_Isle_Server
return Packet;
}
public static byte[] CreateSecCode(byte[] SecCodeSeed, int SecCodeInc, bool Admin, bool Moderator)
{
MemoryStream ms = new MemoryStream();
@ -500,6 +556,21 @@ namespace Horse_Isle_Server
return Packet;
}
public static byte[] CreateKickMessage(string reason)
{
MemoryStream ms = new MemoryStream();
ms.WriteByte(PACKET_KICK);
byte[] strBytes = Encoding.UTF8.GetBytes(reason);
ms.Write(strBytes, 0x00, strBytes.Length);
ms.WriteByte(PACKET_TERMINATOR);
ms.Seek(0x00, SeekOrigin.Begin);
byte[] Packet = ms.ToArray();
ms.Dispose();
return Packet;
}
public static byte[] CreateAreaMessage(int x, int y)
{
string locationStr = Messages.FormatLocationData(x, y);
@ -510,7 +581,7 @@ namespace Horse_Isle_Server
string formattedMotd = Messages.FormatMOTD();
return CreateAnnouncement(formattedMotd);
}
public static byte[] CreateLoginMessage(string username)
public static byte[] CreateWelcomeMessage(string username)
{
string formattedStr = Messages.FormatLoginMessage(username);
return CreateChat(formattedStr, CHAT_BOTTOM_RIGHT);

View file

@ -17,6 +17,7 @@ namespace Horse_Isle_Server
Database.OpenDatabase();
Map.OpenMap();
Gamedata.ReadGamedata();
World.ReadWorldData();
Server.StartServer();
}

View file

@ -5,6 +5,7 @@ using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Horse_Isle_Server
@ -13,8 +14,25 @@ namespace Horse_Isle_Server
{
public static Socket ServerSocket;
public static List<Client> ConnectedClients = new List<Client>();
public static Client[] ConnectedClients // Done to prevent Enumerator Changed errors.
{
get {
return connectedClients.ToArray();
}
}
public static int IdleTimeout;
public static int IdleWarning;
// used for world time,
private static int gameTickSpeed = 4320; // Changing this to ANYTHING else will cause desync with the client.
private static Timer serverTimer;
private static List<Client> connectedClients = new List<Client>();
public static void OnCrossdomainPolicyRequest(Client sender) // When a cross-domain-policy request is received.
{
Logger.DebugPrint("Cross-Domain-Policy request received from: " + sender.RemoteIp);
@ -35,28 +53,36 @@ namespace Horse_Isle_Server
User user = sender.LoggedinUser;
byte[] MovementPacket = PacketBuilder.CreateMovementPacket(user.X, user.Y, user.CharacterId, PacketBuilder.DIRECTION_DOWN, PacketBuilder.DIRECTION_LOGIN, true);
byte[] MovementPacket = PacketBuilder.CreateMovementPacket(user.X, user.Y, user.CharacterId, user.Facing, PacketBuilder.DIRECTION_TELEPORT, true);
sender.SendPacket(MovementPacket);
byte[] LoginMessage = PacketBuilder.CreateLoginMessage(user.Username);
sender.SendPacket(LoginMessage);
byte[] WelcomeMessage = PacketBuilder.CreateWelcomeMessage(user.Username);
sender.SendPacket(WelcomeMessage);
World.Time time = World.GetGameTime();
int timestamp = time.hours * 60;
timestamp += time.minutes;
byte[] WorldData = PacketBuilder.CreateWorldData(timestamp, time.days, time.year, World.GetWeather());
byte[] WorldData = PacketBuilder.CreateWorldData(World.ServerTime.Minutes, World.ServerTime.Days, World.ServerTime.Years, World.GetWeather());
sender.SendPacket(WorldData);
byte[] SecCodePacket = PacketBuilder.CreateSecCode(user.SecCodeSeeds, user.SecCodeInc, user.Administrator, user.Moderator);
sender.SendPacket(SecCodePacket);
byte[] BaseStatsPacketData = PacketBuilder.CreateBaseStats(user.Money, Server.GetNumberOfPlayers(), user.MailBox.MailCount);
byte[] BaseStatsPacketData = PacketBuilder.CreatePlayerData(user.Money, Server.GetNumberOfPlayers(), user.MailBox.MailCount);
sender.SendPacket(BaseStatsPacketData);
byte[] AreaMessage = PacketBuilder.CreateAreaMessage(user.X, user.Y);
sender.SendPacket(AreaMessage);
foreach(Client client in ConnectedClients)
{
if (client.LoggedIn)
{
if(client.LoggedinUser.Id != user.Id)
{
byte[] PlayerInfo = PacketBuilder.CreatePlayerInfoUpdateOrCreate(client.LoggedinUser.X, client.LoggedinUser.Y, client.LoggedinUser.Facing, client.LoggedinUser.CharacterId, client.LoggedinUser.Username);
sender.SendPacket(PlayerInfo);
}
}
}
byte[] IsleData = PacketBuilder.CreatePlaceData(World.Isles.ToArray(), World.Towns.ToArray(), World.Areas.ToArray());
sender.SendPacket(IsleData);
@ -68,24 +94,24 @@ namespace Horse_Isle_Server
}
public static void OnUpdatePacket(Client sender, byte[] packet)
public static void OnKeepAlive(Client sender, byte[] packet)
{
if (!sender.LoggedIn)
{
Logger.ErrorPrint(sender.RemoteIp + " Requested user information when not logged in.");
Logger.ErrorPrint(sender.RemoteIp + " Requested update when not logged in.");
return;
}
if (packet.Length < 2)
{
Logger.ErrorPrint(sender.LoggedinUser.Username + " Sent an invalid Update Packet");
Logger.ErrorPrint(sender.LoggedinUser.Username + " Sent an invalid update Packet");
return;
}
if(packet[1] == PacketBuilder.PACKET_A_TERMINATOR)
if(packet[1] == PacketBuilder.PACKET_CLIENT_TERMINATOR)
{
Logger.DebugPrint(sender.LoggedinUser.Username + " Requested latest statistics (Money/Playercount/Mail)");
byte[] packetResponse = PacketBuilder.CreateBaseStats(sender.LoggedinUser.Money, GetNumberOfPlayers(), sender.LoggedinUser.MailBox.MailCount);
sender.SendPacket(packetResponse);
Logger.DebugPrint("Sending "+ sender.LoggedinUser.Username +" updated info...");
UpdatePlayer(sender);
}
}
public static void OnProfilePacket(Client sender, byte[] packet)
@ -131,6 +157,7 @@ namespace Horse_Isle_Server
sender.SendPacket(chatPacket);
UpdateArea(sender);
UpdateUserInfo(sender.LoggedinUser);
}
}
@ -148,64 +175,70 @@ namespace Horse_Isle_Server
if(movementDirection == PacketBuilder.MOVE_UP)
{
loggedInUser.Facing = PacketBuilder.DIRECTION_UP;
if (Map.CheckPassable(loggedInUser.X, loggedInUser.Y - 1))
{
loggedInUser.Y -= 1;
byte[] moveUpResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, PacketBuilder.DIRECTION_UP, PacketBuilder.DIRECTION_UP, true);
byte[] moveUpResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, sender.LoggedinUser.Facing, PacketBuilder.DIRECTION_UP, true);
sender.SendPacket(moveUpResponse);
}
else
{
byte[] moveUpResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, PacketBuilder.DIRECTION_UP, PacketBuilder.DIRECTION_NONE, false);
byte[] moveUpResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, sender.LoggedinUser.Facing, PacketBuilder.DIRECTION_NONE, false);
sender.SendPacket(moveUpResponse);
}
}
else if(movementDirection == PacketBuilder.MOVE_LEFT)
{
loggedInUser.Facing = PacketBuilder.DIRECTION_LEFT;
if (Map.CheckPassable(loggedInUser.X - 1, loggedInUser.Y))
{
loggedInUser.X -= 1;
byte[] moveLeftResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, PacketBuilder.DIRECTION_LEFT, PacketBuilder.DIRECTION_LEFT, true);
byte[] moveLeftResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, loggedInUser.Facing, PacketBuilder.DIRECTION_LEFT, true);
sender.SendPacket(moveLeftResponse);
}
else
{
byte[] moveLeftResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, PacketBuilder.DIRECTION_LEFT, PacketBuilder.DIRECTION_NONE, false);
byte[] moveLeftResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, loggedInUser.Facing, PacketBuilder.DIRECTION_NONE, false);
sender.SendPacket(moveLeftResponse);
}
}
else if(movementDirection == PacketBuilder.MOVE_RIGHT)
{
loggedInUser.Facing = PacketBuilder.DIRECTION_RIGHT;
if (Map.CheckPassable(loggedInUser.X + 1, loggedInUser.Y))
{
loggedInUser.X += 1;
byte[] moveLeftResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, PacketBuilder.DIRECTION_RIGHT, PacketBuilder.DIRECTION_RIGHT, true);
byte[] moveLeftResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, loggedInUser.Facing, PacketBuilder.DIRECTION_RIGHT, true);
sender.SendPacket(moveLeftResponse);
}
else
{
byte[] moveLeftResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, PacketBuilder.DIRECTION_RIGHT, PacketBuilder.DIRECTION_NONE, false);
byte[] moveLeftResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, loggedInUser.Facing, PacketBuilder.DIRECTION_NONE, false);
sender.SendPacket(moveLeftResponse);
}
}
else if(movementDirection == PacketBuilder.MOVE_DOWN)
{
loggedInUser.Facing = PacketBuilder.DIRECTION_DOWN;
if (Map.CheckPassable(loggedInUser.X, loggedInUser.Y + 1))
{
loggedInUser.Y += 1;
byte[] moveDownResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, PacketBuilder.DIRECTION_DOWN, PacketBuilder.DIRECTION_DOWN, true);
byte[] moveDownResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, loggedInUser.Facing, PacketBuilder.DIRECTION_DOWN, true);
sender.SendPacket(moveDownResponse);
}
else
{
byte[] moveDownResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, PacketBuilder.DIRECTION_DOWN, PacketBuilder.DIRECTION_NONE, false);
byte[] moveDownResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, loggedInUser.Facing, PacketBuilder.DIRECTION_NONE, false);
sender.SendPacket(moveDownResponse);
}
}
UpdateArea(sender);
UpdateUserInfo(sender.LoggedinUser);
UpdateArea(sender);
}
public static void OnChatPacket(Client sender, byte[] packet)
@ -228,11 +261,15 @@ namespace Horse_Isle_Server
Chat.ChatChannel channel = (Chat.ChatChannel)packet[1];
string message = packetStr.Substring(2, packetStr.Length - 4);
Logger.DebugPrint(sender.LoggedinUser.Username + " Attempting to say '" + message + "' in channel: " + channel.ToString("X"));
Logger.DebugPrint(sender.LoggedinUser.Username + " Attempting to say '" + message + "' in channel: " + channel.ToString());
string nameTo = null;
if (channel == Chat.ChatChannel.Dm)
nameTo = Chat.GetDmRecipiant(message);
Object violationReason = Chat.FilterMessage(message);
if (violationReason != null) // This is such a hack, but i really couldnt think of any better way to do it.
if (violationReason != null)
{
sender.LoggedinUser.ChatViolations += 1;
string chatViolationMessage = Messages.FormatGlobalChatViolationMessage((Chat.Reason)violationReason);
@ -241,10 +278,22 @@ namespace Horse_Isle_Server
return;
}
Client[] recipiants = Chat.GetRecipiants(sender.LoggedinUser, channel);
byte chatSide = Chat.GetSide(channel);
message = Chat.DoCorrections(message);
message = Chat.EscapeMessage(message);
string failedReason = Chat.NonViolationChecks(sender.LoggedinUser, message);
if (failedReason != null)
{
byte[] failedMessage = PacketBuilder.CreateChat(failedReason, PacketBuilder.CHAT_BOTTOM_RIGHT);
sender.SendPacket(failedMessage);
return;
}
Client[] recipiants = Chat.GetRecipiants(sender.LoggedinUser, channel, nameTo);
// Finally send chat message.
string formattedMessage = Chat.FormatChatForOthers(sender.LoggedinUser,channel,message);
string formattedMessageSender = Chat.FormatChatForSender(sender.LoggedinUser, channel, message);
byte[] chatPacketOthers = PacketBuilder.CreateChat(formattedMessage, chatSide);
@ -258,6 +307,7 @@ namespace Horse_Isle_Server
// Send to sender
sender.SendPacket(chatPacketSender);
}
public static void OnLoginRequest(Client sender, byte[] packet)
{
Logger.DebugPrint("Login request received from: " + sender.RemoteIp);
@ -270,7 +320,7 @@ namespace Horse_Isle_Server
return;
}
if(packet[1] != PacketBuilder.PACKET_A_TERMINATOR)
if(packet[1] != PacketBuilder.PACKET_CLIENT_TERMINATOR)
{
string[] loginParts = loginRequestString.Split('|');
if (loginParts.Length < 3)
@ -290,11 +340,23 @@ namespace Horse_Isle_Server
// Obtain user information
int userId = Database.GetUserid(username);
sender.Login(userId);
sender.LoggedinUser.Password = password;
byte[] ResponsePacket = PacketBuilder.CreateLoginPacket(true);
sender.SendPacket(ResponsePacket);
Logger.DebugPrint(sender.RemoteIp + " Logged into : " + sender.LoggedinUser.Username + " (ADMIN: " + sender.LoggedinUser.Administrator + " MOD: " + sender.LoggedinUser.Moderator+")");
// Send login message
byte[] loginMessageBytes = PacketBuilder.CreateChat(Messages.FormatLoginMessage(sender.LoggedinUser.Username), PacketBuilder.CHAT_BOTTOM_LEFT);
foreach (Client client in ConnectedClients)
if (client.LoggedIn)
if (!client.LoggedinUser.MuteLogins)
if(client.LoggedinUser.Id != userId)
client.SendPacket(loginMessageBytes);
UpdateUserInfo(sender.LoggedinUser);
}
else
{
@ -306,21 +368,81 @@ namespace Horse_Isle_Server
}
public static void OnDisconnect(Client sender)
{
if(sender.LoggedIn)
{
// Send disconnect message
byte[] logoutMessageBytes = PacketBuilder.CreateChat(Messages.FormatLogoutMessage(sender.LoggedinUser.Username), PacketBuilder.CHAT_BOTTOM_LEFT);
foreach (Client client in ConnectedClients)
if (client.LoggedIn)
if (!client.LoggedinUser.MuteLogins)
if (client.LoggedinUser.Id != sender.LoggedinUser.Id)
client.SendPacket(logoutMessageBytes);
// Tell clients of diconnect (remove from chat)
byte[] playerRemovePacket = PacketBuilder.CreatePlayerLeavePacket(sender.LoggedinUser.Username);
foreach (Client client in ConnectedClients)
if (client.LoggedIn)
if (client.LoggedinUser.Id != sender.LoggedinUser.Id)
client.SendPacket(playerRemovePacket);
}
connectedClients.Remove(sender);
}
public static void UpdateArea(Client forClient)
{
if (!forClient.LoggedIn)
{
Logger.ErrorPrint(forClient.RemoteIp + "tried to update tile information when not logged in.");
return;
}
byte[] areaData = PacketBuilder.CreateAreaMessage(forClient.LoggedinUser.X, forClient.LoggedinUser.Y);
forClient.SendPacket(areaData);
}
public static void UpdateWorld(Client forClient)
{
if (!forClient.LoggedIn)
{
Logger.ErrorPrint(forClient.RemoteIp + "tried to update world information when not logged in.");
return;
}
byte[] WorldData = PacketBuilder.CreateWorldData(World.ServerTime.Minutes, World.ServerTime.Days, World.ServerTime.Years, World.GetWeather());
forClient.SendPacket(WorldData);
}
public static void UpdatePlayer(Client forClient)
{
if (!forClient.LoggedIn)
{
Logger.ErrorPrint(forClient.RemoteIp + "tried to update player information when not logged in.");
return;
}
byte[] PlayerData = PacketBuilder.CreatePlayerData(forClient.LoggedinUser.Money, Server.GetNumberOfPlayers(), forClient.LoggedinUser.MailBox.MailCount);
forClient.SendPacket(PlayerData);
}
public static void UpdateUserInfo(User user)
{
byte[] playerInfoBytes = PacketBuilder.CreatePlayerInfoUpdateOrCreate(user.X, user.Y, user.Facing, user.CharacterId, user.Username);
foreach (Client client in ConnectedClients)
if (client.LoggedIn)
if (client.LoggedinUser.Id != user.Id)
client.SendPacket(playerInfoBytes);
}
public static int GetNumberOfPlayers()
{
int count = 0;
foreach(Client client in ConnectedClients)
{
if (client.LoggedIn)
count++;
if(!client.LoggedinUser.Stealth)
count++;
}
return count;
}
@ -349,6 +471,10 @@ namespace Horse_Isle_Server
return count;
}
private static void onTick(object state)
{
World.TickWorldClock();
}
public static void StartServer()
{
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
@ -358,13 +484,15 @@ namespace Horse_Isle_Server
Logger.DebugPrint("Binding to ip: " + ConfigReader.BindIP + " On port: " + ConfigReader.Port.ToString());
ServerSocket.Listen(10000);
while(true)
serverTimer = new Timer(new TimerCallback(onTick), null, gameTickSpeed, gameTickSpeed);
while (true)
{
Logger.DebugPrint("Waiting for new connections...");
Socket cientSocket = ServerSocket.Accept();
Client client = new Client(cientSocket);
ConnectedClients.Add(client);
connectedClients.Add(client);
}
}
}

View file

@ -22,8 +22,12 @@ namespace Horse_Isle_Server
public bool MuteSocials = false;
public bool MuteLogins = false;
public bool Stealth = false;
public int Facing;
public Mailbox MailBox;
public Friends Friends;
public string Password; // For chat filter.
public int ChatViolations
{
get
@ -157,7 +161,7 @@ namespace Horse_Isle_Server
Id = UserId;
Username = Database.GetUsername(UserId);
Administrator = Database.CheckUserIsAdmin(Username);
Moderator = Database.CheckUserIsModerator(Username);
@ -166,6 +170,8 @@ namespace Horse_Isle_Server
y = Database.GetPlayerY(UserId);
charId = Database.GetPlayerCharId(UserId);
Facing = PacketBuilder.DIRECTION_DOWN;
money = Database.GetPlayerMoney(UserId);
bankMoney = Database.GetPlayerBankMoney(UserId);
@ -181,6 +187,7 @@ namespace Horse_Isle_Server
SecCodeSeeds[2] = (byte)rng.Next(40, 140);
SecCodeInc = (byte)rng.Next(0, 99);
// Make some friends! (Get a life!)
Friends = new Friends(this);

View file

@ -38,39 +38,47 @@ namespace Horse_Isle_Server
public struct Time
{
public int minutes;
public int hours;
public int days;
public int year;
public int Minutes;
public int Days;
public int Years;
}
public const int MINUTE = 4320;
public static Time ServerTime = new Time();
public static List<Isle> Isles = new List<Isle>();
public static List<Town> Towns = new List<Town>();
public static List<Area> Areas = new List<Area>();
public static Time GetGameTime()
public static void TickWorldClock()
{
int epoch = Database.GetServerCreationTime();
DateTime serverCreationTime = DateTimeOffset.FromUnixTimeSeconds(epoch).DateTime;
DateTime currentTime = DateTime.Now;
ServerTime.Minutes += 1;
TimeSpan difference = (currentTime.Date - currentTime.Date);
int hours = ServerTime.Minutes / 60;
int totalMilis = Convert.ToInt32(difference.TotalMilliseconds);
// Periodically write time to database:
if (ServerTime.Minutes % 10 == 0) // every 10-in-game minutes)
Database.SetServerTime(ServerTime.Minutes, ServerTime.Days, ServerTime.Years);
int gameMinutes = totalMilis / MINUTE;
int gameHours = (totalMilis / MINUTE * 600);
int gameDays = (totalMilis / (MINUTE * 60) * 24);
int gameYears = ((totalMilis / (MINUTE * 60) * 24)*365);
if (hours == 24) // 1 day
{
ServerTime.Days += 1;
ServerTime.Minutes = 0;
}
Time time = new Time();
time.days = gameDays;
time.year = gameYears;
time.minutes = gameMinutes;
time.hours = gameHours;
if (ServerTime.Days == 366) // 1 year!
{
ServerTime.Days = 0;
ServerTime.Years += 1;
}
}
return time;
public static void ReadWorldData()
{
Logger.DebugPrint("Reading time from database...");
ServerTime.Minutes = Database.GetServerTime();
ServerTime.Days = Database.GetServerDay();
ServerTime.Years = Database.GetServerYear();
Logger.InfoPrint("It is " + ServerTime.Minutes / 60 + ":" + ServerTime.Minutes % 60 + " on Day " + ServerTime.Days + " in Year " + ServerTime.Years + "!!!");
}
public static bool InArea(int x, int y)