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

@ -1,17 +1,28 @@
{"messages":{
"login_format":"Welcome to the land of Horse Isle, %USERNAME%!!",
"welcome_format":"Welcome to the land of Horse Isle, %USERNAME%!!",
"motd_format":"<FONT COLOR='#FF0000'><B>Today's Note:</B> %MOTD%</FONT>",
"mail_received":"A message has been sent to you from another player. It is in your inventory now.",
"login_message":"Player %USERNAME% has logged in",
"logout_message":"Player %USERNAME% has disconnected",
"login_format":"Player %USERNAME% has logged in",
"logout_format":"Player %USERNAME% has disconnected",
"profile_save":"Your profile changes were saved.",
"buddy_request":"Attempting to Add Buddy. The other player must click ADD BUDDY as well. (Many players reserve this for just a couple players so don't feel insulted if they do not).",
"drawing_notice":"Drawing not sent to other players when you are not a subscriber.",
"tag":{
"for_sender":"<B>TAG!!</B> %USERNAME% is now it! (tagged by %TAGGER%) [%AMOUNT% buds]",
"for_others":"<B>TAG!!</B> %USERNAME% is now it! (tagged by %TAGGER%)"
},
"commands":{
"mute_help":"<FONT COLOR='#FF0000'><B>PLAYER COMMAND [%COMMAND%] COMPLETED</B></FONT> Mute Channel Not Recognized. (ALL/ADS/GLOBAL/ISLAND/NEAR/HERE/BUDDY/PM/BR/SOCIALS/LOGINS)",
"command_completed":"<FONT COLOR='#FF0000'><B>PLAYER COMMAND [%COMMAND%] COMPLETED</B></FONT>"
},
"disconnect":{
"banned":"Your account has been BANNED. You will no longer be able to login"
"banned":"Your account has been BANNED. You will no longer be able to login",
"client_timeout":{
"warn_after":10,
"kick_after":25,
"warn_message":"You have been idle for %WARN% minutes. You will be disconnected at %KICK% minutes idle",
"kick_message":"%KICK% Minute Player Idle Timeout Reached"
}
},
"login":{
"banned":"Your account has been banned. This occurs when too many rules have been broken",
@ -29,6 +40,112 @@
"bridge_text":"A bridge crosses over the water to another isle. That'll save you some travel costs!"
}
},
"socials":{
"for_sender":{
"friendly":{
"smile":"<FONT COLOR='#BA0042'>* You smile at %USERNAME%. *</FONT>",
"wave":"<FONT COLOR='#BA0042'>* You wave enthusiastically at %USERNAME%! *</FONT>",
"wink":"<FONT COLOR='#BA0042'>* You sneak a wink off to %USERNAME%. *</FONT>",
"laugh":"<FONT COLOR='#BA0042'>* You laugh at %USERNAME%'s humor. *</FONT>",
"high5":"<FONT COLOR='#BA0042'>* You give a big high-five to %USERNAME%! *</FONT>",
"clap":"<FONT COLOR='#BA0042'>* You clap at what %USERNAME% has done! *</FONT>",
"hug":"<FONT COLOR='#BA0042'>* You give %USERNAME% a welcome hug. *</FONT>",
"bearhug":"<FONT COLOR='#BA0042'>* You nearly crush %USERNAME% with your massive bearhug! *</FONT>",
"dance":"<FONT COLOR='#BA0042'>* You do a little dance with %USERNAME%! *</FONT>",
"nod":"<FONT COLOR='#BA0042'>* You nod at %USERNAME%. *</FONT>",
"tickle":"<FONT COLOR='#BA0042'>* You tickle %USERNAME%'s sides. *</FONT>",
"thumbsup":"<FONT COLOR='#BA0042'>* You give %USERNAME% an enthusiastic thumbs up. *</FONT>",
"shoulderpat":"<FONT COLOR='#BA0042'>* You pat %USERNAME% comfortingly on the shoulder. *</FONT>",
"circle":"<FONT COLOR='#BA0042'>* You run circles around %USERNAME% making them dizzy. *</FONT>",
"glomp":"<FONT COLOR='#BA0042'>* You surprise %USERNAME% by tackling and hugging them very tightly! %USERNAME% squeaks in surprise! *</FONT>",
"beam":"<FONT COLOR='#BA0042'>* You produce one of the biggest, happiest faces possible towards %USERNAME%! *</FONT>",
"handshake":"<FONT COLOR='#BA0042'>* You shake hands with %USERNAME% enthusiastically. *</FONT>",
"rofl":"<FONT COLOR='#BA0042'>* %USERNAME% is so funny you end up rolling on the floor from laughing so hard!! *</FONT>",
"spin":"<FONT COLOR='#BA0042'>* You playfully spin %USERNAME% in circles making them dizzy. *</FONT>",
"sing":"<FONT COLOR='#BA0042'>* You sing a silly song to %USERNAME% hoping they laugh. *</FONT>",
"flail":"<FONT COLOR='#BA0042'>* You flail wildly at %USERNAME%! *</FONT>"
},
"unfriendly":{
"frown":"<FONT COLOR='#BA0042'>* You frown upon %USERNAME%'s behavior. *</FONT>",
"poke":"<FONT COLOR='#BA0042'>* You poke %USERNAME% right in the ribs! *</FONT>",
"ignore":"<FONT COLOR='#BA0042'>* You stick your nose in the air and ignore %USERNAME%s childish behavior! *</FONT>",
"growl":"<FONT COLOR='#BA0042'>* In a deep growling voice, you attempt to frighten %USERNAME%! *</FONT>",
"point":"<FONT COLOR='#BA0042'>* You point jokingly at %USERNAME%! *</FONT>",
"burp":"<FONT COLOR='#BA0042'>* BuuuuuuuurrrrP! *</FONT>",
"cry":"<FONT COLOR='#BA0042'>* %USERNAME% has made you cry like a little baby! *</FONT>",
"yell":"<FONT COLOR='#BA0042'>* You start yelling angrily at %USERNAME%. *</FONT>",
"nudge":"<FONT COLOR='#BA0042'>* You nudge %USERNAME% carefully out of your way. *</FONT>",
"yawn":"<FONT COLOR='#BA0042'>* YYYYAAAAWWWWNNNNN... Boy %USERNAME% is boring... *</FONT>",
"tease":"<FONT COLOR='#BA0042'>* You laughingly tease %USERNAME% about their silly shoes. *</FONT>",
"quack":"<FONT COLOR='#BA0042'>* You make weird animal noises at %USERNAME% trying to sound like a ferocious... duck. *</FONT>",
"snore":"<FONT COLOR='#BA0042'>* ZZzzzzz.... %USERNAME% has bored you to the point of SNORING!! Wow.. now, that is boring.. *</FONT>",
"scream":"<FONT COLOR='#BA0042'>* AAAAAAAAAAAAAHHH!!!! You scream loudly at %USERNAME%.. . maybe overreacting? *</FONT>",
"hide":"<FONT COLOR='#BA0042'>* You quickly hide in the shadows, hoping %USERNAME% does not see you. . . *</FONT>",
"trip":"<FONT COLOR='#BA0042'>* Poor %USERNAME% tripped over your giant hobbitty feet!! *</FONT>",
"roar":"<FONT COLOR='#BA0042'>* From the bottom of your being you release the loudest roar possible!. . Only. . on its way out, your voice squeaks a little, and that takes away from the intimidation. . . *</FONT>",
"boo":"<FONT COLOR='#BA0042'>* BOOOOO! You frighten %USERNAME% really bad! They did not see that coming! *</FONT>"
},
"horse":{
"wink":"<FONT COLOR='#BA0042'>* Your horse winks at %USERNAME%. *</FONT>",
"neigh":"<FONT COLOR='#BA0042'>* Your horse neighs loudly at %USERNAME%. *</FONT>",
"whinny":"<FONT COLOR='#BA0042'>* Your horse whinnies softly and happily towards %USERNAME%. *</FONT>",
"snort":"<FONT COLOR='#BA0042'>* Your horse rudely snorts towards %USERNAME%! *</FONT>",
"buck":"<FONT COLOR='#BA0042'>* Your horse bucks you lightly. Must have been excited to see %USERNAME%. *</FONT>"
}
},
"for_others":{
"friendly":{
"smile":"<FONT COLOR='#BA0042'>* %USERNAME% smiles at you. *</FONT>",
"wave":"<FONT COLOR='#BA0042'>* %USERNAME% is waving at you very enthusiastically! *</FONT>",
"wink":"<FONT COLOR='#BA0042'>* %USERNAME% winks at you secretively. *</FONT>",
"laugh":"<FONT COLOR='#BA0042'>* %USERNAME% laughs at your humor. *</FONT>",
"high5":"<FONT COLOR='#BA0042'>* %USERNAME% comes at you with a high-five! You manage to meet the clap in time! *</FONT>",
"clap":"<FONT COLOR='#BA0042'>* %USERNAME% is clapping at what you have accomplished! *</FONT>",
"hug":"<FONT COLOR='#BA0042'>* %USERNAME% gives you a hug. *</FONT>",
"bearhug":"<FONT COLOR='#BA0042'>* %USERNAME% nearly crushes you with a massive bearhug! *</FONT>",
"dance":"<FONT COLOR='#BA0042'>* %USERNAME% and you do a little dance! *</FONT>",
"nod":"<FONT COLOR='#BA0042'>* %USERNAME% nods at you. *</FONT>",
"tickle":"<FONT COLOR='#BA0042'>* %USERNAME% tickles your sides until you fall over laughing. *</FONT>",
"thumbsup":"<FONT COLOR='#BA0042'>* %USERNAME% gives you an enthusiastic thumbs up. *</FONT>",
"shoulderpat":"<FONT COLOR='#BA0042'>* %USERNAME% comfortingly pats you on the shoulder. *</FONT>",
"circle":"<FONT COLOR='#BA0042'>* %USERNAME% excitedly runs circles around you causing your head to spin. *</FONT>",
"glomp":"<FONT COLOR='#BA0042'>* All of a sudden %USERNAME% tackles you and starts to hug you very tightly! You squeak in surprise! *</FONT>",
"beam":"<FONT COLOR='#BA0042'>* %USERNAME% produces one of the biggest, happiest faces you've ever seen towards you!!! Wow, you must have made them happy. *</FONT>",
"handshake":"<FONT COLOR='#BA0042'>* %USERNAME% shakes hands with you enthusiastically. *</FONT>",
"rofl":"<FONT COLOR='#BA0042'>* You were so funny that %USERNAME% is rolling on the floor from laughing so hard!! *</FONT>",
"spin":"<FONT COLOR='#BA0042'>* %USERNAME% playfully spins you in circles. You are getting quite dizzy. *</FONT>",
"sing":"<FONT COLOR='#BA0042'>* %USERNAME% sings you a silly song. You burst out laughing. *</FONT>",
"flail":"<FONT COLOR='#BA0042'>* You must have done something exciting, because %USERNAME% is flailing at you wildly! *</FONT>"
},
"unfriendly":{
"frown":"<FONT COLOR='#BA0042'>* Upon your behavior, %USERNAME% frowns deeply. *</FONT>",
"poke":"<FONT COLOR='#BA0042'>* %USERNAME% has poked you right in the ribs! *</FONT>",
"ignore":"<FONT COLOR='#BA0042'>* %USERNAME% sticks their nose in the air ignoring your childish behavior! *</FONT>",
"growl":"<FONT COLOR='#BA0042'>* You are frightened by a deep growl! It's directed at you from %USERNAME%! *</FONT>",
"point":"<FONT COLOR='#BA0042'>* %USERNAME% points jokingly at you! *</FONT>",
"burp":"<FONT COLOR='#BA0042'>* Buuurrrp! You can't believe %USERNAME% just did that towards you! *</FONT>",
"cry":"<FONT COLOR='#BA0042'>* %USERNAME% is crying like a little baby because of you now! *</FONT>",
"yell":"<FONT COLOR='#BA0042'>* %USERNAME% is yelling at you! You must have done something wrong. *</FONT>",
"nudge":"<FONT COLOR='#BA0042'>* %USERNAME% gives you a careful nudge out of the way. *</FONT>",
"yawn":"<FONT COLOR='#BA0042'>* YYYAAAWWWNN... you are boring %USERNAME%! *</FONT>",
"tease":"<FONT COLOR='#BA0042'>* %USERNAME% laughingly teases you about your silly shoes. *</FONT>",
"quack":"<FONT COLOR='#BA0042'>* %USERNAME% makes weird animal noises at you. Was that a duck? *</FONT>",
"snore":"<FONT COLOR='#BA0042'>* ZZzzzzz.... You have bored %USERNAME% to the point of SNORING!! Ooops! *</FONT>",
"scream":"<FONT COLOR='#BA0042'>* AAAAAAAAAAAAAHHH!!!! %USERNAME% screams loudly at you.. . overreacting a bit!? *</FONT>",
"hide":"<FONT COLOR='#BA0042'>* %USERNAME% quickly hides in the shadows, hoping you do not see them. . . *</FONT>",
"trip":"<FONT COLOR='#BA0042'>* You tripped over %USERNAME%'s giant hobbitty feet!! Poor you! *</FONT>",
"roar":"<FONT COLOR='#BA0042'>* From the bottom of %USERNAME%'s being they release the loudest roar possible towards you!. . Only. . on its way out, their voice squeaks a little, and that takes away from the intimidation. . . *</FONT>",
"boo":"<FONT COLOR='#BA0042'>* BOOOOOOOO! %USERNAME% frightens you really bad! You did not see that coming! *</FONT>"
},
"horse":{
"wink":"<FONT COLOR='#BA0042'>* %USERNAME%'s horse winks at you! *</FONT>",
"neigh":"<FONT COLOR='#BA0042'>* %USERNAME%'s horse neighs loudly at you. *</FONT>",
"whinny":"<FONT COLOR='#BA0042'>* %USERNAME%'s horse whinnies softly and happily towards you. *</FONT>",
"snort":" <FONT COLOR='#BA0042'>* %USERNAME%'s horse rudely snorts towards you! *</FONT>",
"buck":"<FONT COLOR='#BA0042'>* %USERNAME%'s horse bucks lightly. Must have been excited to see you. *</FONT>"
}
}
},
"chat":{
"for_others":{
"global_format":"<FONT COLOR='#880000'><B>%USERNAME%:</B> %MESSAGE%</FONT>",
@ -37,8 +154,11 @@
"admin_format":"<FONT COLOR='#800000'><B>%USERNAME%:</B> %MESSAGE%</FONT>",
"ads_format":"<FONT COLOR='#550055'><B>%USERNAME%:</B> %MESSAGE%</FONT>",
"friend_format":"<FONT COLOR='#CC00CC'><B>%USERNAME%:</B> %MESSAGE%</FONT>",
"here_format":"<FONT COLOR='#222222'><B>%USERNAME%:</B> %MESSAGE%</FONT>",
"near_format":"<B>%USERNAME%:</B> %MESSAGE%",
"isle_format":"<B>%USERNAME%:</B> %MESSAGE%",
"dm_format":"<FONT COLOR='#0000FF'><B>%USERNAME%:</B> %MESSAGE%</FONT>",
"dm_format)moderator":"<FONT COLOR='#0000FF'><B>%USERNAME%[<FONT COLOR='#880000'>mod</FONT>:</B> %MESSAGE%</FONT>"
"dm_format_moderator":"<FONT COLOR='#0000FF'><B>%USERNAME%[<FONT COLOR='#880000'>mod</FONT>:</B> %MESSAGE%</FONT>"
},
"for_sender":{
@ -88,13 +208,16 @@
{"word":"my phone","reason_type":"personal_info","match_all":true},
{"word":"phone number","reason_type":"personal_info","match_all":true},
{"word":"home address","reason_type":"personal_info","match_all":true},
{"word":"http","reason_type":"personal_info","match_all":true},
{"word":"40lb","reason_type":"personal_info","match_all":true}
],
"correct":[
{"word":"lol","new_word":"*laughing out loud!*"},
{"word":"lmao","new_word":"*laughing my horse's rump off*"},
{"word":"lmfao","new_word":"*laughing my horse's rump off*"},
{"word":"rofl","new_word":"*rolling on floor laughing*"},
{"word":"ppp","new_word":"*petting a pretty pony*"},
{"word":"wtf","new_word":"what the horse poo!"},
{"word":"asl","new_word":"how are you"},
{"word":"omg","new_word":"oh my gosh"},
{"word":"god","new_word":"unicorns"},
@ -112,11 +235,13 @@
{"name":"personal_info","message":"No giving out personal info/websites."}
],
"violation_points_required":10,
"violation_format":"<FONT COLOR='#880000'><B>Your last chat was flagged as a possible violation of chat rules to be reviewed by an admin. If it is severe or you have many violations your account may be suspended. We require at least %AMOUNT% violation points before examining an account, so if it was a simple misspelling do not worry. Remember this is a family friendly game! Thanks for keeping it as such! (REASON: %REASON%)</B></FONT>"
"violation_format":"<FONT COLOR='#880000'><B>Your last chat was flagged as a possible violation of chat rules to be reviewed by an admin. If it is severe or you have many violations your account may be suspended. We require at least %AMOUNT% violation points before examining an account, so if it was a simple misspelling do not worry. Remember this is a family friendly game! Thanks for keeping it as such! (REASON: %REASON%)</B></FONT>",
"password_included":"Your Password was included in the chat you attempted to send! DO NOT Give ANYONE your password! If someone was asking for your password, please report them immediately!",
"caps_notice":"Please <B>do not use all CAPS</B>, it looks as if you are yelling."
}
},
"mod_splatterball_game":{
"hit_message":"SMACK!! %USERNAME% hit you with a Mod Splatterball, slimy goop exploded and dripped on you.",
"hit_message":"SMACK!! %USERNAME% hit you with a Mod Splatterball, slimy goop exploded and dripped on you."
},
"water_balloon_game":{
"money_prize":20000,

View file

@ -25,4 +25,12 @@ Not implemented:
"hit_message":"SMACK!! %USERNAME% hit you with a Water Balloon, soaking you.",
"winner_message":"<B>You are a Water Balloon winner!</B> Prize: $%PRIZE%",
"end_message_winner":"<B>WATER BALLOON FIGHT OVER:</B> Here were the winners:<BR>%USERNAME% was hit %AMOUNT% times."
},
},
mod_format FOR SENDER is unconfirmed
mod_format is unconfirmed
admin_format is unconfirmed
admin_format FOR SENDER is unconfirmed.
Near radius is a square, 15x19

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)

Binary file not shown.

Binary file not shown.