no message

This commit is contained in:
SilicaAndPina 2020-10-02 00:44:44 +13:00
parent b4b566f1bf
commit aefd94fb44
17 changed files with 1958 additions and 87 deletions

View file

@ -1,14 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Horse_Isle_Server
{
class Chat
{
private static bool isCommand(User user, string message)
public struct Correction
{
public string FilteredWord;
public string ReplacedWord;
}
public struct Reason
{
public string Name;
public string Message;
}
public struct Filter
{
public string FilteredWord;
public Reason Reason;
public bool MatchAll;
}
public enum ChatChannel
{
All = 0x14,
Ads = 0x1D,
Near = 0x15,
Buddies = 0x17,
Isle = 0x24,
Mod,
Admin
}
public static List<Filter> FilteredWords = new List<Filter>();
public static List<Correction> CorrectedWords = new List<Correction>();
public static List<Reason> Reasons = new List<Reason>();
public static bool ProcessCommand(User user, string message)
{
if (message.Length < 1)
return false;
@ -21,18 +52,80 @@ namespace Horse_Isle_Server
return false;
}
private static bool isAppropriate(string message)
public static Object FilterMessage(string message) // Handles chat filtering and violation stuffs returns
{
if (!ConfigReader.BadWords)
return true;
if (!ConfigReader.BadWords) // Freedom of Speech Mode
return null;
string[] wordsSaid;
if (message.Contains(' '))
wordsSaid = message.Split(' ');
else
return true; // Fuck Censorship
wordsSaid = new string[] { message };
foreach(Filter filter in FilteredWords)
{
if (filter.MatchAll)
{
foreach (string word in wordsSaid)
{
if (word == filter.FilteredWord)
return filter.Reason;
}
}
else
{
if (message.Contains(filter.FilteredWord))
return filter.Reason;
}
}
return null;
}
public static void HandleMessage(User user, byte channel, string message)
public static byte GetSide(ChatChannel channel)
{
switch (channel)
{
case ChatChannel.All:
case ChatChannel.Ads:
case ChatChannel.Isle:
return PacketBuilder.CHAT_BOTTOM_LEFT;
case ChatChannel.Admin:
case ChatChannel.Mod:
case ChatChannel.Buddies:
return PacketBuilder.CHAT_BOTTOM_RIGHT;
default:
Logger.ErrorPrint("unknown channel: " + (byte)channel);
return PacketBuilder.CHAT_BOTTOM_LEFT;
}
}
public static Client[] GetRecipiants(User user, ChatChannel channel)
{
if(channel == ChatChannel.All)
{
List<Client> recipiants = new List<Client>();
foreach (Client client in Server.ConnectedClients)
if (client.LoggedIn)
if (!client.LoggedinUser.MuteGlobal)
recipiants.Add(client);
return recipiants.ToArray();
}
Logger.ErrorPrint(user.Username + " Sent message in unknown channel: " + (byte)channel);
return new Client[0]; // No recipiants
}
public static Reason GetReason(string name)
{
foreach (Reason reason in Reasons)
if (reason.Name == name)
return reason;
throw new KeyNotFoundException("Reason " + name + " not found.");
}
}
}

View file

@ -110,6 +110,9 @@ namespace Horse_Isle_Server
case PacketBuilder.PACKET_PROFILE:
Server.OnProfilePacket(this, Packet);
break;
case PacketBuilder.PACKET_CHAT:
Server.OnChatPacket(this, Packet);
break;
case PacketBuilder.PACKET_UPDATE:
Server.OnUpdatePacket(this, Packet);
break;

View file

@ -90,10 +90,10 @@ namespace Horse_Isle_Server
case "crossdomain":
CrossDomainPolicyFile = data;
break;
case "filter_bad_words":
case "enable_corrections":
BadWords = data == "true";
break;
case "correct_slang":
case "enable_word_filter":
ExpandSlang = data == "true";
break;
case "debug":

View file

@ -14,7 +14,7 @@ namespace Horse_Isle_Server
db = new MySqlConnection("server=" + ConfigReader.DatabaseIP + ";user=" + ConfigReader.DatabaseUsername + ";password=" + ConfigReader.DatabasePassword+";database="+ConfigReader.DatabaseName);
db.Open();
string UserTable = "CREATE TABLE Users(Id INT, Username TEXT(16),Email TEXT(128),Country TEXT(128),SecurityQuestion Text(128),SecurityAnswerHash TEXT(128),Age INT,PassHash TEXT(128), Salt TEXT(128),Gender TEXT(16), Admin TEXT(3), Moderator TEXT(3))";
string ExtTable = "CREATE TABLE UserExt(Id INT, X INT, Y INT, Money INT, BankBalance BIGINT,ProfilePage Text(1028), CharId INT)";
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 WorldTable = "CREATE TABLE World(TimeStarted INT, Weather TEXT(64))";
string DroppedTable = "CREATE TABLE DroppedItems(X INT, Y INT, ItemID INT)";
@ -233,7 +233,7 @@ namespace Horse_Isle_Server
throw new Exception("Userid " + id + " Allready in userext.");
MySqlCommand sqlCommand = db.CreateCommand();
sqlCommand.CommandText = "INSERT INTO UserExt VALUES(@id,@x,@y,0,0,'',0)";
sqlCommand.CommandText = "INSERT INTO UserExt VALUES(@id,@x,@y,0,0,'',0,0)";
sqlCommand.Parameters.AddWithValue("@id", id);
sqlCommand.Parameters.AddWithValue("@x", Map.NewUserStartX);
sqlCommand.Parameters.AddWithValue("@y", Map.NewUserStartY);
@ -342,6 +342,41 @@ namespace Horse_Isle_Server
throw new KeyNotFoundException("Id " + userId + " not found in database.");
}
}
public static int GetChatViolations(int userId)
{
if (CheckUserExtExists(userId))
{
MySqlCommand sqlCommand = db.CreateCommand();
sqlCommand.CommandText = "SELECT ChatViolations FROM UserExt WHERE Id=@id";
sqlCommand.Parameters.AddWithValue("@id", userId);
sqlCommand.Prepare();
int violations = Convert.ToInt32(sqlCommand.ExecuteScalar());
return violations;
}
else
{
throw new KeyNotFoundException("Id " + userId + " not found in database.");
}
}
public static void SetChatViolations(int violations, int id)
{
if (CheckUserExist(id))
{
MySqlCommand sqlCommand = db.CreateCommand();
sqlCommand.CommandText = "UPDATE UserExt SET ChatViolations=@violations WHERE Id=@id";
sqlCommand.Parameters.AddWithValue("@violations", violations);
sqlCommand.Parameters.AddWithValue("@id", id);
sqlCommand.Prepare();
sqlCommand.ExecuteNonQuery();
}
else
{
throw new KeyNotFoundException("Id " + id + " not found in database.");
}
}
public static void SetPlayerY(int y, int id)
{
if (CheckUserExist(id))

View file

@ -71,24 +71,83 @@ namespace Horse_Isle_Server
}
// Register Filter Reasons
int totalReasons = gameData.messages.chat.reason_messages.Count;
for(int i = 0; i < totalReasons; i++)
{
Chat.Reason reason = new Chat.Reason();
reason.Name = gameData.messages.chat.reason_messages[i].name;
reason.Message = gameData.messages.chat.reason_messages[i].message;
Chat.Reasons.Add(reason);
Logger.DebugPrint("Registered Chat Warning Reason: " + reason.Name + " (Message: " + reason.Message + ")");
}
// Register Filters
int totalFilters = gameData.messages.chat.filter.Count;
for(int i = 0; i < totalFilters; i++)
{
Chat.Filter filter = new Chat.Filter();
filter.FilteredWord = gameData.messages.chat.filter[i].word;
filter.MatchAll = gameData.messages.chat.filter[i].match_all;
filter.Reason = Chat.GetReason((string)gameData.messages.chat.filter[i].reason_type);
Chat.FilteredWords.Add(filter);
Logger.DebugPrint("Registered Filtered Word: " + filter.FilteredWord + " With reason: "+filter.Reason.Name+" (Matching all: " + filter.MatchAll + ")");
}
// Register Corrections
int totalCorrections = gameData.messages.chat.correct.Count;
for (int i = 0; i < totalCorrections; i++)
{
Chat.Correction correction = new Chat.Correction();
correction.FilteredWord = gameData.messages.chat.correct[i].word;
correction.ReplacedWord = gameData.messages.chat.correct[i].new_word;
Chat.CorrectedWords.Add(correction);
Logger.DebugPrint("Registered Word Correction: " + correction.FilteredWord + " to "+correction.ReplacedWord);
}
// New Users
Messages.NewUserMessage = gameData.new_user.starting_message;
Map.NewUserStartX = gameData.new_user.starting_x;
Map.NewUserStartY = gameData.new_user.starting_y;
// Announcements
Messages.LoginFormat = gameData.messages.login_format;
Messages.MotdFormat = gameData.messages.motd_format;
Messages.ProfileSavedMessage = gameData.messages.profile_save;
// Chat
Messages.ChatViolationMessageFormat = gameData.messages.chat.violation_format;
Messages.RequiredChatViolations = gameData.messages.chat.violation_points_required;
Messages.GlobalChatFormat = gameData.messages.chat.for_others.global_format;
Messages.GlobalChatFormatForModerators = gameData.messages.chat.for_others.global_format_moderator;
Messages.AdsChatFormat = gameData.messages.chat.for_others.ads_format;
Messages.HereChatFormatForSender = gameData.messages.chat.for_sender.here_format;
Messages.IsleChatFormatForSender = gameData.messages.chat.for_sender.isle_format;
Messages.NearChatFormatForSender = gameData.messages.chat.for_sender.near_format;
Messages.BuddyChatFormatForSender = gameData.messages.chat.for_sender.friend_format;
Messages.DirectChatFormatForSender = gameData.messages.chat.for_sender.dm_format;
// Meta Format
Messages.LocationFormat = gameData.messages.meta.location_format;
Messages.IsleFormat = gameData.messages.meta.isle_format;
Messages.TownFormat = gameData.messages.meta.town_format;
Messages.AreaFormat = gameData.messages.meta.area_format;
Messages.LocationFormat = gameData.messages.meta.location_format;
Messages.Sepeerator = gameData.messages.meta.seperator;
Messages.Seperator = gameData.messages.meta.seperator;
Messages.TileFormat = gameData.messages.meta.tile_format;
Messages.NothingMessage = gameData.messages.meta.nothing_message;
// Map Data
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[]>();

View file

@ -71,6 +71,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Authentication.cs" />
<Compile Include="Chat.cs" />
<Compile Include="Client.cs" />
<Compile Include="Converters.cs" />
<Compile Include="Database.cs" />

View file

@ -8,14 +8,31 @@ namespace Horse_Isle_Server
{
class Messages
{
// Announcements
public static string NewUserMessage;
public static string LoginFormat;
public static string MotdFormat;
// Records
public static string ProfileSavedMessage;
public static string Sepeerator;
// Chat
public static string GlobalChatFormat;
public static string AdsChatFormat;
public static string GlobalChatFormatForModerators;
public static string HereChatFormatForSender;
public static string IsleChatFormatForSender;
public static string NearChatFormatForSender;
public static string BuddyChatFormatForSender;
public static string DirectChatFormatForSender;
public static string ChatViolationMessageFormat;
public static int RequiredChatViolations;
// Meta
public static string IsleFormat;
public static string TownFormat;
public static string AreaFormat;
@ -23,16 +40,32 @@ namespace Horse_Isle_Server
public static string TileFormat;
public static string NothingMessage;
public static string GetMOTD()
public static string Seperator;
public static string FormatGlobalChatViolationMessage(Chat.Reason violationReason)
{
return ChatViolationMessageFormat.Replace("%AMOUNT%", RequiredChatViolations.ToString()).Replace("%REASON%", violationReason.Message);
}
public static string FormatGlobalChatMessage(User sender, string message)
{
if (sender.Moderator)
return GlobalChatFormatForModerators.Replace("%USERNAME%", sender.Username).Replace("%MESSAGE%", message);
else
return GlobalChatFormat.Replace("%USERNAME%", sender.Username).Replace("%MESSAGE%", message);
}
public static string FormatMOTD()
{
return MotdFormat.Replace("%MOTD%", ConfigReader.Motd);
}
public static string GetLoginMessage(string username)
public static string FormatLoginMessage(string username)
{
return LoginFormat.Replace("%USERNAME%", username);
}
public static string LocationData(int x, int y)
public static string FormatLocationData(int x, int y)
{
string locationString = "";
string message = "";

View file

@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Horse_Isle_Server
{
@ -44,6 +41,7 @@ namespace Horse_Isle_Server
public const byte CHAT_BOTTOM_LEFT = 0x14;
public const byte CHAT_BOTTOM_RIGHT = 0x15;
public const byte LOGIN_INVALID_USER_PASS = 0x15;
public const byte LOGIN_SUCCESS = 0x14;
@ -504,17 +502,17 @@ namespace Horse_Isle_Server
public static byte[] CreateAreaMessage(int x, int y)
{
string locationStr = Messages.LocationData(x, y);
string locationStr = Messages.FormatLocationData(x, y);
return CreatePlaceInfo(locationStr);
}
public static byte[] CreateMotd()
{
string formattedMotd = Messages.GetMOTD();
string formattedMotd = Messages.FormatMOTD();
return CreateAnnouncement(formattedMotd);
}
public static byte[] CreateLoginMessage(string username)
{
string formattedStr = Messages.GetLoginMessage(username);
string formattedStr = Messages.FormatLoginMessage(username);
return CreateChat(formattedStr, CHAT_BOTTOM_RIGHT);
}

View file

@ -28,11 +28,12 @@ motd=April 11, 2020. New breed, Camarillo White Horse. Two new quests.
# Wether to block 'bad' words
# ex 'Fuck You!' gets blocked
filter_bad_words=true
enable_word_filter=true
# Wether to expand slang.
# ex 'lol' becomes '*laughing out loud!*'
correct_slang=true
# (NOTE: This feature is also used to filter some less-'bad' words disabling it will allow users to say them!)
enable_corrections=true
# Should print debug logs
# Should print extra debug logs
debug=false

View file

@ -32,45 +32,42 @@ namespace Horse_Isle_Server
return;
}
Logger.DebugPrint(sender.LoggedinUser.Username + " Requested user information.");
MemoryStream ms = new MemoryStream();
User user = sender.LoggedinUser;
byte[] MovementPacket = PacketBuilder.CreateMovementPacket(user.X, user.Y, user.CharacterId, PacketBuilder.DIRECTION_DOWN, PacketBuilder.DIRECTION_LOGIN, true);
ms.Write(MovementPacket, 0x00, MovementPacket.Length);
sender.SendPacket(MovementPacket);
byte[] LoginMessage = PacketBuilder.CreateLoginMessage(user.Username);
ms.Write(LoginMessage, 0x00, LoginMessage.Length);
sender.SendPacket(LoginMessage);
World.Time time = World.GetGameTime();
int timestamp = time.hours * 60;
timestamp += time.minutes;
byte[] WorldData = PacketBuilder.CreateWorldData(timestamp, time.days, time.year, World.GetWeather());
ms.Write(WorldData, 0x00, WorldData.Length);
sender.SendPacket(WorldData);
byte[] SecCodePacket = PacketBuilder.CreateSecCode(user.SecCodeSeeds, user.SecCodeInc, user.Administrator, user.Moderator);
ms.Write(SecCodePacket, 0x00, SecCodePacket.Length);
Logger.DebugPrint("SecCode: [5] == "+SecCodePacket[5]+" dump: " + BitConverter.ToString(SecCodePacket).Replace('-', ' '));
sender.SendPacket(new byte[] { 0x81, 0x7C, 0x70, 0x73, 0x26, 0x41, 0x00 });
byte[] BaseStatsPacketData = PacketBuilder.CreateBaseStats(user.Money, Server.GetNumberOfPlayers(), user.MailBox.MailCount);
ms.Write(BaseStatsPacketData, 0x00, BaseStatsPacketData.Length);
sender.SendPacket(BaseStatsPacketData);
byte[] AreaMessage = PacketBuilder.CreateAreaMessage(user.X, user.Y);
ms.Write(AreaMessage, 0x00, AreaMessage.Length);
sender.SendPacket(AreaMessage);
byte[] IsleData = PacketBuilder.CreatePlaceData(World.Isles.ToArray(), World.Towns.ToArray(), World.Areas.ToArray());
ms.Write(IsleData, 0x00, IsleData.Length);
sender.SendPacket(IsleData);
byte[] TileFlags = PacketBuilder.CreateTileOverlayFlags(Map.OverlayTileDepth);
ms.Write(TileFlags, 0x00, TileFlags.Length);
sender.SendPacket(TileFlags);
byte[] MotdData = PacketBuilder.CreateMotd();
ms.Write(MotdData, 0x00, MotdData.Length);
sender.SendPacket(MotdData);
ms.Seek(0x00, SeekOrigin.Begin);
byte[] Packet = ms.ToArray();
ms.Dispose();
sender.SendPacket(Packet);
}
public static void OnUpdatePacket(Client sender, byte[] packet)
{
@ -211,7 +208,52 @@ namespace Horse_Isle_Server
UpdateArea(sender);
}
public static void OnChatPacket(Client sender, byte[] packet)
{
if (!sender.LoggedIn)
{
Logger.ErrorPrint(sender.RemoteIp + " Sent chat packet when not logged in.");
return;
}
if(packet.Length < 4)
{
Logger.ErrorPrint(sender.RemoteIp + " Sent an invalid chat packet.");
return;
}
string packetStr = Encoding.UTF8.GetString(packet);
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"));
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.
{
sender.LoggedinUser.ChatViolations += 1;
string chatViolationMessage = Messages.FormatGlobalChatViolationMessage((Chat.Reason)violationReason);
byte[] chatViolationPacket = PacketBuilder.CreateChat(chatViolationMessage, PacketBuilder.CHAT_BOTTOM_RIGHT);
sender.SendPacket(chatViolationPacket);
return;
}
Client[] recipiants = Chat.GetRecipiants(sender.LoggedinUser, channel);
byte chatSide = Chat.GetSide(channel);
string formattedMessage = Messages.FormatGlobalChatMessage(sender.LoggedinUser, message);
byte[] chatPacket = PacketBuilder.CreateChat(formattedMessage, chatSide);
// Send to clients ...
foreach (Client recipiant in recipiants)
{
recipiant.SendPacket(chatPacket);
}
}
public static void OnLoginRequest(Client sender, byte[] packet)
{
Logger.DebugPrint("Login request received from: " + sender.RemoteIp);
@ -247,6 +289,8 @@ namespace Horse_Isle_Server
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+")");
}
else
{

View file

@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Horse_Isle_Server
{
@ -13,8 +10,32 @@ namespace Horse_Isle_Server
public bool Administrator;
public bool Moderator;
public bool NewPlayer = false;
public bool MuteAds = false;
public bool MuteGlobal = false;
public bool MuteIsland = false;
public bool MuteNear = false;
public bool MuteHere = false;
public bool MuteBuddy = false;
public bool MutePM = false;
public bool MuteBR = false;
public bool MuteSocials = false;
public bool MuteLogins = false;
public Mailbox MailBox;
public int ChatViolations
{
get
{
return chatViolations;
}
set
{
Database.SetChatViolations(value,Id);
chatViolations = value;
}
}
public string ProfilePage {
get
{
@ -92,6 +113,7 @@ namespace Horse_Isle_Server
}
}
private int chatViolations;
private int charId;
private string profilePage;
private int x;
@ -139,6 +161,7 @@ namespace Horse_Isle_Server
Administrator = Database.CheckUserIsAdmin(Username);
Moderator = Database.CheckUserIsModerator(Username);
chatViolations = Database.GetChatViolations(UserId);
x = Database.GetPlayerX(UserId);
y = Database.GetPlayerY(UserId);
charId = Database.GetPlayerCharId(UserId);
@ -153,10 +176,10 @@ namespace Horse_Isle_Server
// Generate SecCodes
Random rng = new Random();
SecCodeSeeds[0] = (byte)rng.Next(0, 255 - 33);
SecCodeSeeds[1] = (byte)rng.Next(0, 255 - 33);
SecCodeSeeds[2] = (byte)rng.Next(0, 255 - 33);
SecCodeInc = (byte)rng.Next(0, 255 - 33);
SecCodeSeeds[0] = (byte)rng.Next(40, 140);
SecCodeSeeds[1] = (byte)rng.Next(40, 140);
SecCodeSeeds[2] = (byte)rng.Next(40, 140);
SecCodeInc = (byte)rng.Next(0, 99);
}
}