mirror of
https://github.com/SoDOff-Project/sodoff-mmo.git
synced 2025-10-11 08:18:49 -07:00
I am definitely overengineering this...
This commit is contained in:
parent
909ec91a72
commit
ec5621d904
@ -11,6 +11,7 @@ class ChatMessageHandler : CommandHandler {
|
||||
string message = receivedObject.Get<NetworkObject>("p").Get<string>("chm");
|
||||
if (ManagementCommandProcessor.ProcessCommand(message, client))
|
||||
return Task.CompletedTask;
|
||||
if (CheckIllegalName(client)) return Task.CompletedTask;
|
||||
if (client.TempMuted) {
|
||||
ClientMuted(client);
|
||||
return Task.CompletedTask;
|
||||
@ -23,6 +24,14 @@ class ChatMessageHandler : CommandHandler {
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public static bool CheckIllegalName(Client client) {
|
||||
if (client.PlayerData.DiplayName.Equals("Server", StringComparison.InvariantCultureIgnoreCase)) {
|
||||
client.Send(Utils.BuildServerSideMessage("You may not use chat with that name.", "Server"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ChatDisabled(Client client) {
|
||||
client.Send(Utils.BuildServerSideMessage("Unfortunately, chat has been disabled by server administrators", "Server"));
|
||||
}
|
||||
@ -38,7 +47,7 @@ class ChatMessageHandler : CommandHandler {
|
||||
}
|
||||
|
||||
client.Room.Send(Utils.BuildChatMessage(client.PlayerData.Uid, message, client.PlayerData.DiplayName), client);
|
||||
DiscordManager.SendMessage(client.PlayerData.DiplayName+">"+message, client.Room);
|
||||
DiscordManager.SendPlayerBasedMessage(message, ":speech_balloon: {1}>{0}", client.Room, client.PlayerData);
|
||||
|
||||
NetworkObject cmd = new();
|
||||
NetworkObject data = new();
|
||||
|
@ -1,6 +1,7 @@
|
||||
using sodoffmmo.Attributes;
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Data;
|
||||
using sodoffmmo.Management;
|
||||
|
||||
namespace sodoffmmo.CommandHandlers;
|
||||
|
||||
@ -8,6 +9,43 @@ namespace sodoffmmo.CommandHandlers;
|
||||
class GenericMessageHandler : CommandHandler {
|
||||
public override Task Handle(Client client, NetworkObject receivedObject) {
|
||||
NetworkPacket packet = NetworkObject.WrapObject(0, 7, receivedObject).Serialize();
|
||||
if (receivedObject.Get<object>("m") is string message) {
|
||||
if (message.StartsWith("C:")) { // chat
|
||||
if (!ChatMessageHandler.CheckIllegalName(client)) {
|
||||
bool sent = false;
|
||||
if (int.TryParse(message.AsSpan(2), out int num)) {
|
||||
string? text = Configuration.GetVersioned(num, client.GameVersion, Configuration.CannedChat);
|
||||
if (text != null) {
|
||||
DiscordManager.SendPlayerBasedMessage("", ":loudspeaker: {1}>"+text, client.Room, client.PlayerData);
|
||||
sent = true;
|
||||
}
|
||||
}
|
||||
if (!sent) DiscordManager.SendPlayerBasedMessage(message.Substring(2), ":loudspeaker: {1}>*Unknown quickchat {0}*", client.Room, client.PlayerData);
|
||||
} else {
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
} else if (message.StartsWith("EID:")) { // Emoticons
|
||||
bool sent = false;
|
||||
if (int.TryParse(message.AsSpan(4), out int num)) {
|
||||
string? text = Configuration.GetVersioned(num, client.GameVersion, Configuration.Emoticons);
|
||||
if (text != null) {
|
||||
DiscordManager.SendPlayerBasedMessage("", ":wireless: {1} used "+text, client.Room, client.PlayerData);
|
||||
sent = true;
|
||||
}
|
||||
}
|
||||
if (!sent) DiscordManager.SendPlayerBasedMessage(message.Substring(4), ":wireless: {1} used *unknown emoticon {0}*", client.Room, client.PlayerData);
|
||||
} else if (message.StartsWith("AID:")) { // Actions
|
||||
bool sent = false;
|
||||
if (int.TryParse(message.AsSpan(4), out int num)) {
|
||||
string? text = Configuration.GetVersioned(num, client.GameVersion, client.PlayerData.EMDDriving() ? Configuration.EMDCarActions : Configuration.Actions);
|
||||
if (text != null) {
|
||||
DiscordManager.SendPlayerBasedMessage("", ":dancer: {1} performed "+text, client.Room, client.PlayerData);
|
||||
sent = true;
|
||||
}
|
||||
}
|
||||
if (!sent) DiscordManager.SendPlayerBasedMessage(message.Substring(4), ":dancer: {1} performed *unknown action {0}*", client.Room, client.PlayerData);
|
||||
}
|
||||
}
|
||||
client.Room.Send(packet);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
@ -86,6 +86,8 @@ class LoginHandler : CommandHandler
|
||||
if (info.Authenticated) {
|
||||
client.PlayerData.DiplayName = info.DisplayName;
|
||||
client.PlayerData.Role = info.Role;
|
||||
client.PlayerData.VikingId = info.Id;
|
||||
client.GameVersion = info.Version;
|
||||
return true;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
using sodoffmmo.Data;
|
||||
using sodoffmmo.Management;
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.CompilerServices;
|
||||
@ -18,6 +19,7 @@ public class Client {
|
||||
SocketBuffer socketBuffer = new();
|
||||
private volatile bool scheduledDisconnect = false;
|
||||
private readonly object clientLock = new();
|
||||
public uint GameVersion { get; set; }
|
||||
|
||||
public Client(Socket clientSocket) {
|
||||
socket = clientSocket;
|
||||
@ -59,6 +61,7 @@ public class Client {
|
||||
data.Add("r", Room.Id);
|
||||
data.Add("u", ClientID);
|
||||
Room.Send(NetworkObject.WrapObject(0, 1004, data).Serialize());
|
||||
DiscordManager.SendPlayerBasedMessage("", ":red_square: {1} has left the room.", Room, PlayerData);
|
||||
}
|
||||
|
||||
// set new room (null when SetRoom is used as LeaveRoom)
|
||||
@ -70,6 +73,7 @@ public class Client {
|
||||
|
||||
Send(Room.SubscribeRoom());
|
||||
if (Room.Name != "LIMBO") UpdatePlayerUserVariables(); // do not update user vars if room is limbo
|
||||
DiscordManager.SendPlayerBasedMessage("", ":green_square: {1} has joined the room.", Room, PlayerData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
@ -10,9 +13,15 @@ internal static class Configuration {
|
||||
|
||||
public static ServerConfiguration ServerConfiguration { get; private set; } = new ServerConfiguration();
|
||||
|
||||
public static SortedDictionary<int, object> Emoticons = new();
|
||||
public static SortedDictionary<int, object> Actions = new();
|
||||
public static SortedDictionary<int, object> EMDCarActions = new();
|
||||
public static SortedDictionary<int, object> CannedChat = new();
|
||||
|
||||
public static void Initialize() {
|
||||
IConfigurationRoot config = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json", true)
|
||||
.AddJsonFile("emote_data.json", true)
|
||||
.Build();
|
||||
|
||||
ServerConfiguration? serverConfiguration = config.GetSection("MMOServer").Get<ServerConfiguration>();
|
||||
@ -23,6 +32,45 @@ internal static class Configuration {
|
||||
if (string.IsNullOrEmpty(ServerConfiguration.ApiUrl)) {
|
||||
ServerConfiguration.Authentication = AuthenticationMode.Disabled;
|
||||
}
|
||||
|
||||
// Emoticons (the emojis that float above your head)
|
||||
SortAndVersion(config.GetSection("Emoticons"), Emoticons);
|
||||
// Actions (such as dances)
|
||||
SortAndVersion(config.GetSection("Actions"), Actions);
|
||||
// In EMD, there are seperate actions when in car that share IDs with normal actions.
|
||||
// Since this is easy to check MMO-side (SPM uservar), we can just store these seperate
|
||||
SortAndVersion(config.GetSection("EMDCarActions"), EMDCarActions);
|
||||
// Canned Chat options (which can vary game to game)
|
||||
SortAndVersion(config.GetSection("CannedChat"), CannedChat);
|
||||
}
|
||||
|
||||
// While version checking isn't exactly necessary for Actions when using vanilla files, it's nice to support it anyway.
|
||||
private static void SortAndVersion(IConfigurationSection section, IDictionary<int, object> dataOut) {
|
||||
foreach (IConfigurationSection config in section.GetChildren()) {
|
||||
if (config.Value != null) {
|
||||
// Consistent for all games
|
||||
dataOut.Add(int.Parse(config.Key), config.Value);
|
||||
} else {
|
||||
// Requires version checks
|
||||
OrderedDictionary versioned = new();
|
||||
dataOut.Add(int.Parse(config.Key), versioned);
|
||||
foreach (IConfigurationSection version in config.GetChildren().OrderByDescending(v=>uint.Parse(v.Key))) {
|
||||
versioned.Add(uint.Parse(version.Key, NumberStyles.AllowHexSpecifier), version.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string? GetVersioned(int id, uint version, IDictionary<int, object> data) {
|
||||
object? value = data[id];
|
||||
if (value is null or string) {
|
||||
return value as string;
|
||||
} else if (value is OrderedDictionary versions) {
|
||||
foreach (DictionaryEntry ver in versions)
|
||||
if (version >= (uint)ver.Key)
|
||||
return (string)ver.Value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Globalization;
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Management;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace sodoffmmo.Data;
|
||||
public class PlayerData {
|
||||
@ -37,6 +38,7 @@ public class PlayerData {
|
||||
|
||||
public string DiplayName { get; set; } = "placeholder";
|
||||
public Role Role { get; set; } = Role.User;
|
||||
public int VikingId { get; set; }
|
||||
|
||||
public long last_ue_time { get; set; } = 0;
|
||||
|
||||
@ -90,6 +92,25 @@ public class PlayerData {
|
||||
value = FixMountState(value);
|
||||
}
|
||||
|
||||
// update the playername (sent with avatardata) if it changes
|
||||
// this is also hit when the player joins the room
|
||||
if (varName == "A" && variables.GetValueOrDefault("A") != value) {
|
||||
try {
|
||||
// Gonna surround this in a try/catch in case for some
|
||||
// reason it breaks so that it doesn't break MMO.
|
||||
string? name = JsonSerializer.Deserialize<AvatarData>(value)?.DisplayName;
|
||||
if (name != null && name != DiplayName) {
|
||||
string msg = ":label: {1} has changed their name to {0}";
|
||||
if (name.Equals("Server", StringComparison.InvariantCultureIgnoreCase)) {
|
||||
msg += ". *This name will block them from speaking.*";
|
||||
}
|
||||
DiscordManager.SendPlayerBasedMessage(name, msg, player: this);
|
||||
DiplayName = name;
|
||||
}
|
||||
}
|
||||
catch (Exception) {} // Pokemon-style exception handling
|
||||
}
|
||||
|
||||
// store in directory
|
||||
variables[varName] = value;
|
||||
return value;
|
||||
@ -211,6 +232,10 @@ public class PlayerData {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool EMDDriving() {
|
||||
return variables.TryGetValue("SPM", out string? value) && value == "Driver";
|
||||
}
|
||||
}
|
||||
|
||||
public enum PetGeometryType {
|
||||
|
@ -12,6 +12,12 @@ public class AuthenticationInfo {
|
||||
|
||||
[XmlElement]
|
||||
public Role Role { get; set; }
|
||||
|
||||
[XmlElement]
|
||||
public int Id { get; set; }
|
||||
|
||||
[XmlElement]
|
||||
public uint Version { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
11
src/Management/AvatarData.cs
Normal file
11
src/Management/AvatarData.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace sodoffmmo.Management;
|
||||
|
||||
public class AvatarData {
|
||||
public string? DisplayName { get; set; }
|
||||
}
|
@ -4,6 +4,8 @@ using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Collections.Concurrent;
|
||||
using sodoffmmo.Core;
|
||||
using Discord.Rest;
|
||||
using sodoffmmo.Data;
|
||||
|
||||
namespace sodoffmmo.Management;
|
||||
|
||||
@ -51,69 +53,278 @@ class DiscordManager {
|
||||
return;
|
||||
}
|
||||
client = new DiscordSocketClient(new DiscordSocketConfig {
|
||||
GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.MessageContent
|
||||
GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.GuildMembers | GatewayIntents.MessageContent,
|
||||
AlwaysDownloadUsers = true
|
||||
});
|
||||
client.Ready += OnBotReady;
|
||||
client.Ready += async () => {
|
||||
channel = client.GetGuild(config.Server).GetTextChannel(config.Channel);
|
||||
};
|
||||
client.MessageReceived += OnDiscordMessage;
|
||||
await client.LoginAsync(TokenType.Bot, config.Token);
|
||||
DiscordManager.config = config;
|
||||
Log("Loaded bot config from "+token_file+" and bot is running.");
|
||||
await client.StartAsync();
|
||||
while (true) {
|
||||
if (queue.TryDequeue(out QueuedMessage message)) {
|
||||
SocketTextChannel? destination = channel;
|
||||
if (message.room != null) {
|
||||
string room = message.room.Name;
|
||||
destination = channel.Threads.SingleOrDefault(x => x.Name == room);
|
||||
if (destination == null) {
|
||||
// A discord channel can have up to 1000 active threads
|
||||
// and an unlimited number of archived threads.
|
||||
if (message.room.AutoRemove) {
|
||||
// Set temporary rooms (such as user rooms) to shorter archive times.
|
||||
destination = await channel.CreateThreadAsync(room, autoArchiveDuration: ThreadArchiveDuration.OneDay);
|
||||
} else {
|
||||
// Persistent rooms should stay around for longer.
|
||||
destination = await channel.CreateThreadAsync(room, autoArchiveDuration: ThreadArchiveDuration.OneWeek);
|
||||
}
|
||||
foreach (SocketGuildUser? user in channel.Users) {
|
||||
await ((SocketThreadChannel)destination).AddUserAsync(user);
|
||||
try {
|
||||
if (!queue.IsEmpty && queue.TryDequeue(out QueuedMessage message)) {
|
||||
SocketTextChannel? destination = channel;
|
||||
if (message.room != null) {
|
||||
if (message.room.Name == "LIMBO") continue;
|
||||
string room = message.room.Name;
|
||||
destination = channel.Threads.SingleOrDefault(x => x.Name == room);
|
||||
if (destination == null) {
|
||||
// A discord channel can have up to 1000 active threads
|
||||
// and an unlimited number of archived threads.
|
||||
if (message.room.AutoRemove) {
|
||||
// Set temporary rooms (such as user rooms) to shorter archive times.
|
||||
destination = await channel.CreateThreadAsync(room, autoArchiveDuration: ThreadArchiveDuration.OneHour);
|
||||
} else {
|
||||
// Persistent rooms should stay around for longer.
|
||||
destination = await channel.CreateThreadAsync(room, autoArchiveDuration: ThreadArchiveDuration.OneWeek);
|
||||
}
|
||||
}
|
||||
}
|
||||
await destination.SendMessageAsync(message.msg);
|
||||
}
|
||||
await destination.SendMessageAsync(message.msg);
|
||||
} catch (Exception e) {
|
||||
Log(e.ToString(), ConsoleColor.Red);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task OnBotReady() {
|
||||
channel = client.GetGuild(config.Server).GetTextChannel(config.Channel);
|
||||
}
|
||||
|
||||
// For handling commands sent directly in the channel.
|
||||
private static async Task OnDiscordMessage(SocketMessage arg) {
|
||||
// Check that message is from a user in the correct place.
|
||||
if (arg.Channel.Id != config.Channel || arg is not SocketUserMessage socketMessage || socketMessage.Author.IsBot) return;
|
||||
bool roomChannel = arg.Channel is SocketThreadChannel thr && thr.ParentChannel.Id == config.Channel;
|
||||
if (!(
|
||||
arg.Channel.Id == config.Channel ||
|
||||
roomChannel
|
||||
) ||
|
||||
arg is not SocketUserMessage socketMessage ||
|
||||
socketMessage.Author.IsBot
|
||||
) return;
|
||||
|
||||
string[] message = socketMessage.Content.Split(' ');
|
||||
if (message.Length >= 1) {
|
||||
if (message[0] == "help") {
|
||||
SendMessage("No-one can help you.");
|
||||
string[] everywhereCommands = new string[] {
|
||||
// Denotes commands that work identically regardless
|
||||
// of whether you're in a room thread.
|
||||
"!tempmute <int: vikingid> [string... reason] - Mute someone until they reconnect."
|
||||
};
|
||||
bool un_command = message[0].StartsWith("!un");
|
||||
if (message[0] == "!tempmute" || message[0] == "!untempmute") {
|
||||
if (message.Length > 1 && int.TryParse(message[1], out int id)) {
|
||||
foreach (Room room in Room.AllRooms()) {
|
||||
foreach (Client player in room.Clients) {
|
||||
if (player.PlayerData.VikingId == id) {
|
||||
if (player.TempMuted != un_command) {
|
||||
await arg.Channel.SendMessageAsync($"This player is {(un_command ? "not" : "already")} tempmuted.", messageReference: arg.Reference);
|
||||
} else {
|
||||
player.TempMuted = !un_command;
|
||||
string reason = string.Empty;
|
||||
string msg = un_command ? "Un-tempmuted" : "Tempmuted";
|
||||
msg += $" {player.PlayerData.DiplayName}.";
|
||||
if (message.Length >= 2) {
|
||||
reason = string.Join(' ', message, 2, message.Length - 2);
|
||||
msg += " Reason: "+reason;
|
||||
}
|
||||
await arg.Channel.SendMessageAsync(msg, messageReference: arg.Reference);
|
||||
}
|
||||
goto tempmute_search_loop_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
tempmute_search_loop_end:;// StackOverflow said to do it like this (no labeled break like in Java).
|
||||
} else {
|
||||
await arg.Channel.SendMessageAsync("Input a valid vikingid!", messageReference: arg.Reference);
|
||||
}
|
||||
} else if (roomChannel) {
|
||||
if (message[0] == "!help") {
|
||||
await arg.Channel.SendMessageAsync(string.Join(Environment.NewLine, new string[] {
|
||||
"### List of commands:",
|
||||
"!help - Prints the help message. That's this message right here!",
|
||||
"!list - Lists all players in this room.",
|
||||
"!say <string... message> - Say something in this room."
|
||||
}.Concat(everywhereCommands)
|
||||
));
|
||||
} else if (message[0] == "!list") {
|
||||
if (!Room.Exists(arg.Channel.Name)) {
|
||||
await arg.Channel.SendMessageAsync("This room is currently unloaded.", messageReference: arg.Reference);
|
||||
} else {
|
||||
Room room = Room.Get(arg.Channel.Name);
|
||||
if (room.ClientsCount > 0) {
|
||||
string msg = "Players in Room:\n";
|
||||
foreach (Client player in room.Clients) {
|
||||
string vikingid;
|
||||
if (player.PlayerData.VikingId != 0) {
|
||||
vikingid = "||VikingId: "+player.PlayerData.VikingId+"||";
|
||||
} else {
|
||||
vikingid = "||(Not Authenticated!)||";
|
||||
}
|
||||
msg += $"* {SanitizeString(player.PlayerData.DiplayName)} {vikingid}\n";
|
||||
}
|
||||
SendMessage(msg, room); // Sent like this in case it's longer than 2000 characters (handled by this method).
|
||||
} else {
|
||||
await arg.Channel.SendMessageAsync("This room is empty.", messageReference: arg.Reference);
|
||||
}
|
||||
}
|
||||
} else if (message[0] == "!say") {
|
||||
if (message.Length > 1) {
|
||||
// Due to client-based restrictions, this probably only works in SoD and maybe MaM.
|
||||
// Unless we want to create an MMOAvatar instance for the server "user".
|
||||
if (Room.Exists(arg.Channel.Name)) {
|
||||
Room room = Room.Get(arg.Channel.Name);
|
||||
if (room.ClientsCount > 0) {
|
||||
room.Send(Utils.BuildChatMessage(Guid.Empty.ToString(), string.Join(' ', message, 1, message.Length-1), "Server"));
|
||||
await arg.AddReactionAsync(Emote.Parse(":white_check_mark:"));
|
||||
} else {
|
||||
await arg.Channel.SendMessageAsync("There is no-one in this room to see your message.", messageReference: arg.Reference);
|
||||
}
|
||||
} else {
|
||||
await arg.Channel.SendMessageAsync("This room is currently unloaded.", messageReference: arg.Reference);
|
||||
}
|
||||
} else {
|
||||
await arg.Channel.SendMessageAsync("You didn't include any message content!", messageReference: arg.Reference);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (message[0] == "!help") {
|
||||
await arg.Channel.SendMessageAsync(string.Join(Environment.NewLine, new string[] {
|
||||
"### List of commands:",
|
||||
"!help - Prints the help message. That's this message right here!",
|
||||
"!rooms - Ping you in all active Room threads you aren't already in.",
|
||||
" This will add you to all of the room threads. :warning: **This may generate a lot of pings for you!** :warning:",
|
||||
"!list - Lists all players on the server."
|
||||
}.Concat(everywhereCommands)
|
||||
.Append("*Using !help in a room thread yields a different set of commands. Try using !help in a room thread!*")
|
||||
));
|
||||
} else if (message[0] == "!rooms") {
|
||||
IEnumerable<RestThreadChannel> threads = await channel.GetActiveThreadsAsync();
|
||||
Console.WriteLine(threads.Count());
|
||||
ulong uid = socketMessage.Author.Id;
|
||||
foreach (RestThreadChannel thread in threads) {
|
||||
// If the user is already in the thread no need to ping them.
|
||||
if (await thread.GetThreadUsersAsync().Flatten().AnyAsync(user => user.Id == uid)) continue;
|
||||
|
||||
// Ping the user and then delete the message.
|
||||
RestUserMessage ping = await thread.SendMessageAsync("<@"+uid+"> making this thread visible for you ;)");
|
||||
await ping.DeleteAsync();
|
||||
}
|
||||
} else if (message[0] == "!list") {
|
||||
string msg = string.Empty;
|
||||
foreach (Room room in Room.AllRooms()) {
|
||||
foreach (Client player in room.Clients) {
|
||||
if (msg == string.Empty) msg = "Players Online:\n";
|
||||
|
||||
string vikingid;
|
||||
if (player.PlayerData.VikingId != 0) {
|
||||
vikingid = "||VikingId: "+player.PlayerData.VikingId+"||";
|
||||
} else {
|
||||
vikingid = "||(Not Authenticated!)||";
|
||||
}
|
||||
msg += $"* {SanitizeString(player.PlayerData.DiplayName)} {vikingid} ({room.Name})\n";
|
||||
}
|
||||
}
|
||||
if (msg == string.Empty) {
|
||||
await arg.Channel.SendMessageAsync("Nobody is online.", messageReference: arg.Reference);
|
||||
} else {
|
||||
SendMessage(msg); // Sent like this in case it's longer than 2000 characters (handled by this method).
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a message through the bot.
|
||||
/// If the message is larger than 2000 characters it will be split until if fit.
|
||||
/// </summary>
|
||||
/// <param name="msg">Message to send</param>
|
||||
/// <param name="room">Room to send message in - can be null</param>
|
||||
public static void SendMessage(string msg, Room? room=null) {
|
||||
if (client != null) queue.Enqueue(new QueuedMessage {
|
||||
msg = msg
|
||||
.Replace("*", "\\*") // Prevent most Discord formatting
|
||||
.Replace("_", "\\_") // Prevent some other formatting
|
||||
.Replace("~", "\\~") // Prevent Strikethrough
|
||||
.Replace("`", "\\`") // Prevent Code Blocks
|
||||
.Replace(":", "\\:") // Prevent Links
|
||||
.Replace("<", "\\<") // So that Masked Links with embed disabled don't look strange
|
||||
.Replace("](", "]\\("), // Prevent Masked Links
|
||||
room = room
|
||||
});
|
||||
if (client != null) {
|
||||
while (msg.Length > 0) {
|
||||
string piece = msg;
|
||||
if (msg.Length > 2000) { // Discord character limit is 2000.
|
||||
// Find a good place to break the message, if possible.
|
||||
int breakIndex = msg.LastIndexOfAny(new char[2] {' ','\n'}, 2000);
|
||||
if (breakIndex <= 0) breakIndex = 2000;
|
||||
// Split the first part of the message and recycle the rest.
|
||||
piece = msg.Substring(0, breakIndex);
|
||||
msg = msg.Substring(breakIndex);
|
||||
} else {
|
||||
// Exit the loop when the time comes.
|
||||
msg = string.Empty;
|
||||
}
|
||||
queue.Enqueue(new QueuedMessage {
|
||||
msg = piece,
|
||||
room = room
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message through the bot, but include data about the user and sanitize it.
|
||||
/// </summary>
|
||||
/// <param name="msg">Message to send</param>
|
||||
/// <param name="surround">
|
||||
/// Surround the message using formatting.
|
||||
/// {0} corresponds to sanitized msg.
|
||||
/// {1} correspongs to sanitaize playername.
|
||||
/// </param>
|
||||
/// <param name="room">Room to send message in - can be null</param>
|
||||
/// <param name="player">PlayerData to associate the message with - can be null</param>
|
||||
public static void SendPlayerBasedMessage(string msg, string surround="{1} **-->** {0}", Room? room=null, PlayerData? player=null) {
|
||||
try {
|
||||
if (client != null) {
|
||||
// We need to sanitize things first so that people can't
|
||||
// use Discord's formatting features inside a chat message.
|
||||
msg = SanitizeString(msg);
|
||||
string name = SanitizeString(player?.DiplayName ?? "");
|
||||
|
||||
if (player != null) {
|
||||
if (player.VikingId != 0) {
|
||||
surround = "||VikingId: "+player.VikingId+"||\n"+surround;
|
||||
} else {
|
||||
surround = "||(Not Authenticated!)||\n"+surround;
|
||||
}
|
||||
}
|
||||
|
||||
// Send the sanitized message, headed with the viking id (if authenticated).
|
||||
SendMessage(string.Format(surround, msg, name), room);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log(e.ToString(), ConsoleColor.Red);
|
||||
}
|
||||
}
|
||||
|
||||
public static string SanitizeString(string str) {
|
||||
string sanitizedStr = "";
|
||||
for (int i=0;i<str.Length;i++) {
|
||||
char c = str[i];
|
||||
if (
|
||||
c == '\\' ||// Cleanse any attempts to evade the sanitization below
|
||||
c == '*' || // Cleanse most text decoration
|
||||
c == '_' || // Cleanse some other text decoration
|
||||
c == '~' || // Cleanse Strikethrough text decoration
|
||||
c == '`' || // Cleanse Code Snippet text decoration
|
||||
c == ':' || // Cleanse Links, Emojis, and Timestamps
|
||||
(c&0b11111101) == '<' || // Cleanse indirect pings and channel links, and prevents cleansed versions Masked Links with embed disabled from looking strange
|
||||
// By AND-ing the value by 0b11111101, it will affect both '<' and '>'
|
||||
(i > 0 && c == '(' && str[i-1] == ']') // Cleanse Masked Links themselves
|
||||
) {
|
||||
sanitizedStr += '\\'; // Add a backslash to escape it.
|
||||
}
|
||||
if (c == '@') { // Cleanse pings to @everyone and @here
|
||||
sanitizedStr += "`@`";
|
||||
} else {
|
||||
// Append the character as normal, unless
|
||||
// overridden in the single case above.
|
||||
sanitizedStr += c;
|
||||
}
|
||||
}
|
||||
return sanitizedStr;
|
||||
}
|
||||
|
||||
class BotConfig {
|
||||
|
@ -61,7 +61,7 @@
|
||||
"// Authentication Optional": "authentication is required only for moderation activities",
|
||||
"// Authentication RequiredForChat": "authentication is required only for moderation activities and using chat (if chat is enabled)",
|
||||
"// Authentication Required": "authentication is required to connect to mmo",
|
||||
"Authentication": "Disabled",
|
||||
"Authentication": "Optional",
|
||||
|
||||
"// ApiUrl": "SoDOff API server URL for authentication calls",
|
||||
"ApiUrl": "http://localhost:5000",
|
||||
|
969
src/emote_data.json
Normal file
969
src/emote_data.json
Normal file
@ -0,0 +1,969 @@
|
||||
{
|
||||
"Emoticons": {
|
||||
"1": {
|
||||
"04000001": ":grimacing:",
|
||||
"04000000": ":nauseated_face:",
|
||||
"0": ":grimacing:"
|
||||
},
|
||||
"2": ":confused:",
|
||||
"3": ":sunglasses:",
|
||||
"4": ":cry:",
|
||||
"5": ":smiling_imp:",
|
||||
"6": ":flushed:",
|
||||
"7": ":grinning:",
|
||||
"8": ":headphones:",
|
||||
"9": ":rage:",
|
||||
"10": {
|
||||
"02000000": ":person_with_crown:",
|
||||
"0": ":prince:"
|
||||
},
|
||||
"11": ":laughing:",
|
||||
"12": ":heart_eyes:",
|
||||
"13": ":ninja:",
|
||||
"14": {
|
||||
"02000000": ":zipper_mouth:",
|
||||
"0": ":partying_face:"
|
||||
},
|
||||
"15": "\\:pirate\\:",
|
||||
"16": {
|
||||
"02000000": "\\:smug\\:",
|
||||
"0": ":person_with_crown:"
|
||||
},
|
||||
"17": ":relieved:",
|
||||
"18": ":slight_frown:",
|
||||
"19": ":innocent:",
|
||||
"20": {
|
||||
"04000001": ":sick:",
|
||||
"04000000": ":thermometer_face:",
|
||||
"0": ":sick:"
|
||||
},
|
||||
"21": ":astonished:",
|
||||
"22": ":yum:",
|
||||
"23": {
|
||||
"02000000": ":partying_face:",
|
||||
"0": ":police_officer:"
|
||||
},
|
||||
"24": ":firefighter:",
|
||||
"25": ":health_worker:",
|
||||
"26": ":mask:",
|
||||
"27": "\\:hunter\\:",
|
||||
"28": ":construction_worker:",
|
||||
"29": ":cat:",
|
||||
"30": ":dog:",
|
||||
"31": ":mouse:",
|
||||
"32": ":balloon:",
|
||||
"33": ":bell:",
|
||||
"34": ":hatched_chick:",
|
||||
"35": ":bomb:",
|
||||
"36": ":books:",
|
||||
"37": ":tropical_fish:",
|
||||
"38": ":butterfly:",
|
||||
"39": ":birthday_cake:",
|
||||
"40": ":camera:",
|
||||
"41": ":candy:",
|
||||
"42": ":cherries",
|
||||
"43": ":timer_clock:",
|
||||
"44": ":four_leaf_clover",
|
||||
"45": ":cookie:",
|
||||
"46": ":sunflower:",
|
||||
"47": ":doughnut:",
|
||||
"48": ":drum:",
|
||||
"49": ":envelope:",
|
||||
"50": ":exclamation:",
|
||||
"51": ":fish:",
|
||||
"52": ":tulip:",
|
||||
"53": ":french_fries:",
|
||||
"54": ":cooking:",
|
||||
"55": ":gem:",
|
||||
"56": ":ghost:",
|
||||
"57": ":gift:",
|
||||
"58": ":green_apple:",
|
||||
"59": ":hamburger:",
|
||||
"60": ":heart:",
|
||||
"61": ":trumpet:",
|
||||
"62": ":hotdog:",
|
||||
"63": ":house:",
|
||||
"64": ":icecream:",
|
||||
"65": ":lady_beetle:",
|
||||
"66": ":computer:",
|
||||
"67": ":leaves:",
|
||||
"68": ":zap:",
|
||||
"69": ":lollipop:",
|
||||
"70": ":magnet:",
|
||||
"71": ":mag_right:",
|
||||
"72": "\\:mittens\\:",
|
||||
"73": ":crescent_moon:",
|
||||
"74": "\\:muffin\\:",
|
||||
"75": ":brown_mushroom:",
|
||||
"76": ":musical_note:",
|
||||
"77": ":tangerine:",
|
||||
"78": ":pancakes:",
|
||||
"79": ":hyacinth:",
|
||||
"80": ":peach:",
|
||||
"81": ":pear:",
|
||||
"82": ":pie:",
|
||||
"83": ":pizza:",
|
||||
"84": ":popcorn:",
|
||||
"85": ":jack_o_lantern:",
|
||||
"86": ":question_mark:",
|
||||
"87": ":rose:",
|
||||
"88": ":santa:",
|
||||
"89": ":shield:",
|
||||
"90": ":shopping_cart:",
|
||||
"91": ":skull:",
|
||||
"92": ":snowflake:",
|
||||
"93": ":socks:",
|
||||
"94": ":flying_saucer:",
|
||||
"95": ":star:",
|
||||
"96": "\\:starfish\\:",
|
||||
"97": ":stopwatch:",
|
||||
"98": ":sun:",
|
||||
"99": ":taco:",
|
||||
"100": ":trophy:",
|
||||
"101": ":poultry_leg:"
|
||||
},
|
||||
"Actions": {
|
||||
"1": "Fist Pump",
|
||||
"2": "Excited",
|
||||
"3": "Shrug",
|
||||
"4": "Toe Touch",
|
||||
"5": "Sad",
|
||||
"6": "Hello",
|
||||
"7": "Flex",
|
||||
"8": "Yes",
|
||||
"9": "Salute",
|
||||
"10": "Pushup",
|
||||
"11": "Come Here",
|
||||
"12": "Clap",
|
||||
"13": "Laugh",
|
||||
"14": "Chin-Up",
|
||||
"15": "No Way",
|
||||
"16": "Listen Up",
|
||||
"17": "Bye",
|
||||
"18": "Kisses",
|
||||
"19": "Break Dance",
|
||||
"20": "Cabbage Patch",
|
||||
"21": "Head Banger",
|
||||
"22": "Macarena",
|
||||
"23": "Running Man",
|
||||
"24": "Shy",
|
||||
"25": "Ta Da!",
|
||||
"26": "Talk",
|
||||
"27": "Yawn",
|
||||
"28": "What!",
|
||||
"29": "Handstand",
|
||||
"30": "Beg",
|
||||
"31": "Rub Head and Pat Stomach",
|
||||
"32": "Cheer",
|
||||
"33": "Scold",
|
||||
"34": "Bow",
|
||||
"35": "Cry",
|
||||
"36": "Dance 01",
|
||||
"37": "Dance 02",
|
||||
"38": "Dance 03",
|
||||
"39": "Dance 04",
|
||||
"40": "Dance 05",
|
||||
"41": "Dance 06"
|
||||
},
|
||||
"EMDCarActions": {
|
||||
"1": "Burn Out",
|
||||
"2": "Donut",
|
||||
"3": "Hydraulics",
|
||||
"4": "Hydraulic Dancing",
|
||||
"5": "Wheel Spin",
|
||||
"6": "Endo",
|
||||
"7": "Wheelie",
|
||||
"8": "Flip"
|
||||
},
|
||||
"CannedChat": {
|
||||
"10001": "Hi.",
|
||||
"10500": "Hello.",
|
||||
"11000": "Hi there.",
|
||||
"11500": "What's up?",
|
||||
"12001": "Greetings.",
|
||||
"12002": "Greetings earthlings.",
|
||||
"12003": {
|
||||
"08000000": "Greetings my fellow Blasters.",
|
||||
"0": "Greetings my fellow Jumpeez."
|
||||
},
|
||||
"12500": "Nice to meet you.",
|
||||
"13000": "Good morning.",
|
||||
"13500": "Good afternoon.",
|
||||
"1400": "Good evening.",
|
||||
"14500": "Hola!",
|
||||
"15000": "Howdy partner!",
|
||||
"20000": "Bye.",
|
||||
"20500": "Goodbye.",
|
||||
"21000": "See ya!",
|
||||
"21500": "Have a great day!",
|
||||
"22001": "See you tomorrow morning.",
|
||||
"22002": "See you tomorrow afternoon.",
|
||||
"22003": "See you tomorrow night.",
|
||||
"22500": "Goodnight.",
|
||||
"23000": "See you later alligator\u2026",
|
||||
"23500": "In a while crocodile!",
|
||||
"24000": "Nice meeting you!",
|
||||
"24500": "Adios!",
|
||||
"25000": "Toodle-loo!",
|
||||
"26000": "Later.",
|
||||
"30001": "I am happy.",
|
||||
"30002": "I am sad.",
|
||||
"30003": "I am excited!",
|
||||
"30004": "I am bored.",
|
||||
"30005": "I am scared.",
|
||||
"30006": "I am surprised!",
|
||||
"30007": "I am hungry.",
|
||||
"30008": "I am tired.",
|
||||
"30009": "I am grumpy.",
|
||||
"30010": "I am amused.",
|
||||
"30050": "I am smart.",
|
||||
"30051": "I am goofy.",
|
||||
"30052": "I am funny.",
|
||||
"30053": "I am serious.",
|
||||
"50054": "I am a cool cat.",
|
||||
"30055": "I am awesome!",
|
||||
"30056": "I am a troublemaker.",
|
||||
"30057": "I am bad to the bone!",
|
||||
"30101": "I am an artist.",
|
||||
"30102": "I am a pirate.",
|
||||
"30103": "I am a prince.",
|
||||
"30104": "I am a princess",
|
||||
"30105": "I am a wizard.",
|
||||
"30106": "I am a mad scientist.",
|
||||
"30107": "I am a scuba diver.",
|
||||
"30108": "I am a gold miner.",
|
||||
"30109": "I am a rock star.",
|
||||
"30110": "I am a movie star.",
|
||||
"30111": "I am a secret agent.",
|
||||
"30112": "I am a singer.",
|
||||
"30113": "I am a writer.",
|
||||
"30150": "I am an athlete.",
|
||||
"30151": "I am a volleyball player.",
|
||||
"30152": "I am a basketball player.",
|
||||
"30153": "I am a baseball player.",
|
||||
"30154": "I am a softball player.",
|
||||
"30155": "I am a football player.",
|
||||
"30156": "I am a hockey player.",
|
||||
"30157": "I am a water polo player.",
|
||||
"30158": "I am a soccer player.",
|
||||
"30159": "I am a tennis player.",
|
||||
"30160": "I am a cheerleader.",
|
||||
"30161": "I am a gymnast.",
|
||||
"30162": "I am a swimmer.",
|
||||
"30200": {
|
||||
"08000000": "I am a Blaster Cadet.",
|
||||
"0": "I am a level 1."
|
||||
},
|
||||
"30201": {
|
||||
"08000000": "I am a Blaster Cadet 1st Class.",
|
||||
"0": "I am a level 2."
|
||||
},
|
||||
"30202": {
|
||||
"08000000": "I am a Blaster Private.",
|
||||
"0": "I am a level 3."
|
||||
},
|
||||
"30203": {
|
||||
"08000000": "I am a Blaster Private 1st Class.",
|
||||
"0": "I am a level 4."
|
||||
},
|
||||
"30204": {
|
||||
"08000000": "I am a Blaster Corporal.",
|
||||
"0": "I am a level 5."
|
||||
},
|
||||
"30205": {
|
||||
"08000000": "I am a Blaster Corporal 1st Class.",
|
||||
"0": "I am a level 6."
|
||||
},
|
||||
"31001": "I like to explore.",
|
||||
"31002": "I like to sing.",
|
||||
"31003": "I like to dance.",
|
||||
"31004": "I like to chat.",
|
||||
"31005": "I like to fly.",
|
||||
"31010": "I like to make friends.",
|
||||
"31011": "I like to learn.",
|
||||
"31020": "I like Alien Wrangler.",
|
||||
"31021": "I like B-Force Blaster.",
|
||||
"31022": "I like Blast Attack.",
|
||||
"31023": "I like Bolt Cruncher.",
|
||||
"31024": "I like Dodge-N-Dash.",
|
||||
"31025": "I like Droid Defense.",
|
||||
"31026": "I like Galaxy Grand Prix.",
|
||||
"31027": "I like Hyper Blast.",
|
||||
"31028": "I like Monster Mutts.",
|
||||
"31029": "I like Morph Madness.",
|
||||
"31030": "I like Oozami.",
|
||||
"31031": "I like Red Alert.",
|
||||
"31032": "I like Roller Ball Rally.",
|
||||
"31033": "I like Zapper.",
|
||||
"31050": {
|
||||
"08000000": "I like the Math Academy.",
|
||||
"0": "I like MainStreet."
|
||||
},
|
||||
"31051": {
|
||||
"08000000": "I like the Spaceport.",
|
||||
"0": "I like DownTown."
|
||||
},
|
||||
"31052": {
|
||||
"08000000": "I like the Ready Room.",
|
||||
"0": "I like the Arcade."
|
||||
},
|
||||
"31053": {
|
||||
"08000000": "I like Planet Avatarus.",
|
||||
"0": "I like New York."
|
||||
},
|
||||
"31054": {
|
||||
"08000000": "I like Planet Blizzard.",
|
||||
"0": "I like the Enchanted Sanctuary."
|
||||
},
|
||||
"31055": {
|
||||
"08000000": "I like the Park.",
|
||||
"0": "I like StoryLand."
|
||||
},
|
||||
"31056": {
|
||||
"08000000": "I like Fitness Training.",
|
||||
"0": "I like AdventureLand."
|
||||
},
|
||||
"31057": {
|
||||
"08000000": "I like the Training Center.",
|
||||
"0": "I like MarineLand."
|
||||
},
|
||||
"31058": {
|
||||
"08000000": "I like the Larva Den.",
|
||||
"0": "I like FutureLand."
|
||||
},
|
||||
"31059": {
|
||||
"08000000": "I like the Alien Wrangler Arena.",
|
||||
"0": "I like Ghost Town Grab"
|
||||
},
|
||||
"31060": {
|
||||
"08000000": "I like my Pod.",
|
||||
"0": "I like Hidden Treasure Hollow."
|
||||
},
|
||||
"31150": "I like cats.",
|
||||
"31151": "I like dogs.",
|
||||
"31152": "I like goldfish.",
|
||||
"31153": "I like hamsters.",
|
||||
"31154": "I like guinea pigs.",
|
||||
"31155": "I like bunnies.",
|
||||
"31156": "I like birds",
|
||||
"31157": "I like snakes.",
|
||||
"31158": "I like turtles.",
|
||||
"31159": "I like frogs.",
|
||||
"31200": "I like tigers.",
|
||||
"31201": "I like lions.",
|
||||
"31202": "I like bears.",
|
||||
"31203": "I like jaguars.",
|
||||
"31204": "I like elephants.",
|
||||
"31205": "I like giraffes.",
|
||||
"31206": "I like hawks.",
|
||||
"31207": "I like dinosaurs.",
|
||||
"31208": "I like unicorns.",
|
||||
"31250": "I like fish.",
|
||||
"31251": "I like sharks.",
|
||||
"31252": "I like dolphins.",
|
||||
"31253": "I like eels.",
|
||||
"31254": "I like stingrays.",
|
||||
"31255": "I like whales.",
|
||||
"31256": "I like jellyfish",
|
||||
"31257": "I like sea turtles.",
|
||||
"31258": "I like penguins.",
|
||||
"31259": "I like sea monsters.",
|
||||
"31300": "I like red.",
|
||||
"31301": "I like orange.",
|
||||
"31302": "I like yellow.",
|
||||
"31303": "I like green.",
|
||||
"31304": "I like blue.",
|
||||
"31305": "I like purple.",
|
||||
"31306": "I like pink.",
|
||||
"31307": "I like white.",
|
||||
"31308": "I like black.",
|
||||
"31309": "I like silver.",
|
||||
"31310": "I like gold.",
|
||||
"31311": "I like brown.",
|
||||
"31350": "I like popsicles.",
|
||||
"31351": "I like pizza.",
|
||||
"31352": "I like hamburgers.",
|
||||
"31353": "I like veggies.",
|
||||
"31354": "I like grilled cheese.",
|
||||
"31355": "I like spaghetti.",
|
||||
"31356": "I like candy.",
|
||||
"31357": "I like ice cream.",
|
||||
"31358": "I like peanut butter.",
|
||||
"31359": "I like cookies.",
|
||||
"31400": "I like to rock out.",
|
||||
"31401": "I like all music.",
|
||||
"31402": "I like hip hop music.",
|
||||
"31403": "I like country music.",
|
||||
"31404": "I like classical music.",
|
||||
"31405": "I like techno music.",
|
||||
"31406": "I like jazz music",
|
||||
"31407": "I like blues music.",
|
||||
"31408": "I like rock music.",
|
||||
"31500": "I like the Ickasaur.",
|
||||
"31501": "I like the Grubble.",
|
||||
"31502": "I like the Eye-Clops.",
|
||||
"31503": "I like the larva.",
|
||||
"32001": "I live near the ocean.",
|
||||
"32002": "I live in the desert.",
|
||||
"32003": "I live in the city.",
|
||||
"32004": "I live on a farm.",
|
||||
"32005": "I live in a tree house.",
|
||||
"32006": "I live in outer space.",
|
||||
"32007": "I live in the jungle.",
|
||||
"32008": "I live on a boat.",
|
||||
"32009": "I live on an island.",
|
||||
"32010": "I live on Mars.",
|
||||
"32011": "I live in a spaceship.",
|
||||
"32012": "I live on Earth.",
|
||||
"32013": "I live with aliens.",
|
||||
"32014": "I live among the stars.",
|
||||
"40001": "Let's dance!",
|
||||
"40002": "Let's race!",
|
||||
"40003": {
|
||||
"08000000": "Let's zap!",
|
||||
"0": "Let's jump!"
|
||||
},
|
||||
"40004": "Let's explore!",
|
||||
"40007": {
|
||||
"08000000": "Add me as a B.F.F.",
|
||||
"0": "Add me as a buddy"
|
||||
},
|
||||
"40008": "Look at that!",
|
||||
"40009": "I am lost.",
|
||||
"40010": "I don't know what to do.",
|
||||
"40011": "Ready...set...go!",
|
||||
"41001": {
|
||||
"08000000": "I am going to train in Hyper Blast.",
|
||||
"0": "I am going to MainStreet."
|
||||
},
|
||||
"41002": {
|
||||
"08000000": "I am going to the Ready Room.",
|
||||
"0": "I am going to DownTown."
|
||||
},
|
||||
"41003": {
|
||||
"08000000": "I am going to B-Force Blaster.",
|
||||
"0": "I am going to the Arcade."
|
||||
},
|
||||
"41004": {
|
||||
"08000000": "I am going to Zapper.",
|
||||
"0": "I am going to New York."
|
||||
},
|
||||
"41005": {
|
||||
"08000000": "I am going to Alien Wrangler.",
|
||||
"0": "I am going to the Enchanted Sanctuary."
|
||||
},
|
||||
"41006": {
|
||||
"08000000": "I am going to play Oozami.",
|
||||
"0": "I am going to StoryLand."
|
||||
},
|
||||
"41007": {
|
||||
"08000000": "I am going to Monster Mutt Rescue.",
|
||||
"0": "I am going to AdventureLand."
|
||||
},
|
||||
"41008": {
|
||||
"08000000": "I am going to Roller Ball Rally.",
|
||||
"0": "I am going to MarineLand."
|
||||
},
|
||||
"41009": {
|
||||
"08000000": "I am going to Morph Madness.",
|
||||
"0": "I am going to FutureLand."
|
||||
},
|
||||
"41010": {
|
||||
"08000000": "I am going to Planet Avatarus.",
|
||||
"0": "I am going to Ghost Town Grab."
|
||||
},
|
||||
"41011": {
|
||||
"08000000": "I am going to Planet Blizzard.",
|
||||
"0": "I am going to Hidden Treasure Hollow."
|
||||
},
|
||||
"41012": {
|
||||
"08000000": "I am going to play Bolt Cruncher.",
|
||||
"0": "I am going to the Amphitheatre."
|
||||
},
|
||||
"41013": {
|
||||
"08000000": "I am going to my Pod.",
|
||||
"0": "I am going to the Stadium."
|
||||
},
|
||||
"41014": {
|
||||
"08000000": "I am going to my Mutt Pod.",
|
||||
"0": "I am going to the Zoo."
|
||||
},
|
||||
"41050": {
|
||||
"08000000": "I am going to tame a wild alien.",
|
||||
"0": "I am going to buy clothes."
|
||||
},
|
||||
"41051": {
|
||||
"08000000": "I am going to change my look.",
|
||||
"0": "I am going to change clothes."
|
||||
},
|
||||
"41052": "I am going to dance.",
|
||||
"41053": "I am going to explore.",
|
||||
"41059": {
|
||||
"08000000": "I am going to decorate my Pod.",
|
||||
"0": "I am going to buy a ride."
|
||||
},
|
||||
"41060": {
|
||||
"08000000": "I am going to throw a party.",
|
||||
"0": "I am going to save Lost Island."
|
||||
},
|
||||
"41061": {
|
||||
"08000000": "I am going to watch a movie.",
|
||||
"0": "I am going to defeat the Punk Punks."
|
||||
},
|
||||
"41062": "I am to rate your Pod.",
|
||||
"41063": "I am going to play with my Monster Mutt.",
|
||||
"41064": "I am going to create some morphs in the Chem Lab.",
|
||||
"50001": "Where are you going?",
|
||||
"50002": "What do you like to do?",
|
||||
"50003": {
|
||||
"08000000": "What rank are you?",
|
||||
"0": "What level are you?"
|
||||
},
|
||||
"50004": "What should we do?",
|
||||
"50005": "Did you see that?",
|
||||
"50006": "Will you follow me?",
|
||||
"50008": "Will you show me your favorite place?",
|
||||
"50009": "Can you show me a secret portal?",
|
||||
"50010": "Did you see the new game?",
|
||||
"50011": {
|
||||
"08000000": "Have you rated my Pod?",
|
||||
"0": "Please unlock my Surprise Box in My House."
|
||||
},
|
||||
"51001": {
|
||||
"08000000": "Want to be my B.F.F.?",
|
||||
"0": "Want to be my friend?"
|
||||
},
|
||||
"51004": "Want to dance?",
|
||||
"51005": {
|
||||
"08000000": "Want to race at G.G.P.?",
|
||||
"0": "Want to race?"
|
||||
},
|
||||
"51006": "Want to explore?",
|
||||
"51007": "Want to play B-Force Blaster?",
|
||||
"51008": "Come to my party in my Pod!",
|
||||
"51009": "Rate my Pod!",
|
||||
"52001": "What is your favorite animal?",
|
||||
"52002": "What is your favorite color?",
|
||||
"52003": "What is your favorite food?",
|
||||
"52004": "What type of music do you like?",
|
||||
"52005": "Where do you live?",
|
||||
"53001": "What did you say?",
|
||||
"60001": "Haha!",
|
||||
"60002": "Hehe!",
|
||||
"60003": "Ho-ho-ho!",
|
||||
"60004": "Tee-he-he!",
|
||||
"60005": "Bwa-ha-ha-ha!",
|
||||
"61001": "Ahoy!",
|
||||
"61002": "Aye aye, captain!",
|
||||
"61003": "Landlubber!",
|
||||
"61004": "Arg!",
|
||||
"61005": "Shiver me timbers!",
|
||||
"61006": "Yo-ho-ho!",
|
||||
"61007": "It's a pirate's life for me.",
|
||||
"61008": "Walk the plank!",
|
||||
"61009": "There be squalls ahead!",
|
||||
"62001": "Woof!",
|
||||
"62002": "Meow!",
|
||||
"62003": "Quack!",
|
||||
"62004": "Roar!",
|
||||
"62005": "Ribbit!",
|
||||
"63001": "Just call me Agent X.",
|
||||
"63002": "Over and out.",
|
||||
"63003": "Sorry, that's classified.",
|
||||
"63004": "My cover is blown!",
|
||||
"63005": "Alpha. Bravo. Charlie. Delta.",
|
||||
"64001": "Error. Does not compute.",
|
||||
"64002": "Beep. Beep.",
|
||||
"64003": "Bzzzurp!",
|
||||
"65001": "Fee fi fo fum!",
|
||||
"65002": "Dun dun dun...",
|
||||
"65003": "Mumbo jumbo!",
|
||||
"65004": "Fiddlesticks!",
|
||||
"65005": "Boogie woogie!",
|
||||
"65006": "La-di-da!",
|
||||
"65007": "Kersplat!",
|
||||
"65008": "Achoo!",
|
||||
"65009": "Blah blah blah...",
|
||||
"66001": "LOL",
|
||||
"66002": "BFF",
|
||||
"66003": "JK",
|
||||
"66004": "IDK",
|
||||
"66005": "PLZ",
|
||||
"66006": "THX",
|
||||
"66007": "BRB",
|
||||
"66008": "CYA",
|
||||
"66009": "TTYL",
|
||||
"80001": "Stop that!",
|
||||
"80002": "Please do not do that.",
|
||||
"80003": "Go away!",
|
||||
"80004": "That is not very nice.",
|
||||
"80005": "You are in my personal bubble.",
|
||||
"80006": "Hurry up!",
|
||||
"80007": "Wait for me!",
|
||||
"80008": "Please slow down.",
|
||||
"80009": {
|
||||
"08000000": "You are a grumpy Blaster.",
|
||||
"0": "You are a grumpy Jumpee."
|
||||
},
|
||||
"70001": "Wow!",
|
||||
"70002": "That was awesome!",
|
||||
"70003": "Super cool!",
|
||||
"70004": "I'm glad you are here.",
|
||||
"71001": "I like your style.",
|
||||
"71002": "I like your outfit.",
|
||||
"71005": "I like your name.",
|
||||
"71006": "I like your hair.",
|
||||
"71008": {
|
||||
"08000000": "I like your mouth.",
|
||||
"0": "I like your pants."
|
||||
},
|
||||
"71009": {
|
||||
"08000000": "I like your boots.",
|
||||
"0": "I like your shoes."
|
||||
},
|
||||
"71010": "I like your eyes.",
|
||||
"71011": {
|
||||
"08000000": "I like your Monster Mutt.",
|
||||
"0": "I like your hat."
|
||||
},
|
||||
"71012": {
|
||||
"08000000": "I like your Pod.",
|
||||
"0": "I like your mythie."
|
||||
},
|
||||
"71013": "I like your Mutt Pod.",
|
||||
"72001": "You are awesome!",
|
||||
"72002": "You are funny!",
|
||||
"72003": "You are pretty.",
|
||||
"72004": "You are handsome.",
|
||||
"72005": "You are kind.",
|
||||
"72006": "You are silly.",
|
||||
"72007": "You are cool.",
|
||||
"72008": "You are great.",
|
||||
"72009": "You are goofy.",
|
||||
"72010": "You are one of a kind.",
|
||||
"72011": "You are my best friend.",
|
||||
"72012": {
|
||||
"08000000": "You are the coolest Blaster!",
|
||||
"0": "You're the coolest Jumpee I know!"
|
||||
},
|
||||
"72013": "You are the bee's knees!",
|
||||
"73001": "Thanks!",
|
||||
"73002": "Thank you!",
|
||||
"73003": "Thanks a bunch!",
|
||||
"73004": "Thanks for being my friend.",
|
||||
"73005": "Thanks for showing me that.",
|
||||
"73006": "You're welcome.",
|
||||
"73007": "No problem!",
|
||||
"73008": "Anytime.",
|
||||
"74001": "Sorry!",
|
||||
"74002": "Oops, sorry!",
|
||||
"74003": "Sorry, I have to go.",
|
||||
"74004": "Sorry, I am busy.",
|
||||
"74005": "Sorry, I didn't mean that.",
|
||||
"74006": "I take it back.",
|
||||
"74007": "It's okay.",
|
||||
"74008": "Don't worry about it.",
|
||||
"74009": "I forgive you.",
|
||||
"90001": "Yes.",
|
||||
"90002": "No.",
|
||||
"90003": "Maybe.",
|
||||
"90004": "Follow me.",
|
||||
"90005": "Me too.",
|
||||
"90006": "Happy Birthday!",
|
||||
"551": "Hello",
|
||||
"552": "Hey!",
|
||||
"553": "Hi",
|
||||
"554": "Hi there.",
|
||||
"555": "Sup?",
|
||||
"556": "Hi, I'm new...",
|
||||
"557": "Nice to meet you.",
|
||||
"558": "How's it goin?",
|
||||
"559": "Hola!",
|
||||
"651": "See ya!",
|
||||
"652": "Good bye.",
|
||||
"653": "L8tr.",
|
||||
"654": "Bye.",
|
||||
"655": "Catch ya!",
|
||||
"656": "See you tomorrow.",
|
||||
"657": "Night!",
|
||||
"658": "Later.",
|
||||
"659": "TTYL",
|
||||
"660": "Take care!",
|
||||
"751": "I am happy.",
|
||||
"752": "I am sooo excited!",
|
||||
"753": "I am scared.",
|
||||
"754": "I am hungry.",
|
||||
"755": "I am good.",
|
||||
"715": "I am sorry.",
|
||||
"756": "I am tired.",
|
||||
"758": "I am heartbroken.",
|
||||
"850": "I am smart.",
|
||||
"851": "I am goofy.",
|
||||
"853": "I am serious.",
|
||||
"854": "I am cool.",
|
||||
"855": "I am awesome!",
|
||||
"856": {
|
||||
"04000000": "I am a racer.",
|
||||
"0": "I am a princess."
|
||||
},
|
||||
"857": "I am laid back!",
|
||||
"858": "I am a dork!",
|
||||
"859": "I am a rebel!",
|
||||
"860": "I am an artist.",
|
||||
"861": "I am a pirate.",
|
||||
"865": "I am a dancer.",
|
||||
"868": "I am a rock star.",
|
||||
"869": "I am a movie star.",
|
||||
"870": "I am a secret agent",
|
||||
"950": "I like to make friends.",
|
||||
"951": "I like to be creative.",
|
||||
"952": "I like to dance.",
|
||||
"953": "I like to chat.",
|
||||
"955": "I like to text.",
|
||||
"956": "I like to learn.",
|
||||
"957": "I like to watch t.v.",
|
||||
"958": "I like to hang with my friends.",
|
||||
"3050": "I like to go to concerts.",
|
||||
"3051": "I like to go to the movies.",
|
||||
"3053": "I like to travel.",
|
||||
"3055": "I like to hangout in my room.",
|
||||
"3056": "I like to hang with my family.",
|
||||
"3150": "I like cats.",
|
||||
"3151": "I like dogs.",
|
||||
"3152": "I like goldfish.",
|
||||
"3153": "I like hamsters.",
|
||||
"3154": "I like sloths.",
|
||||
"3155": "I like bunnies.",
|
||||
"3156": "I like birds",
|
||||
"3157": "I like koalas.",
|
||||
"3158": "I like turtles.",
|
||||
"3159": "I like platypus.",
|
||||
"3250": "I like tigers.",
|
||||
"3251": "I like lions.",
|
||||
"3252": "I like bears.",
|
||||
"3253": "I like jaguars.",
|
||||
"3254": "I like elephants.",
|
||||
"3255": "I like giraffes.",
|
||||
"3256": "I like unicorns.",
|
||||
"3257": "I like Gumby.",
|
||||
"3258": "I like Pokey.",
|
||||
"3350": "I like red.",
|
||||
"3351": "I like orange.",
|
||||
"3352": "I like yellow.",
|
||||
"3353": "I like green.",
|
||||
"3354": "I like blue.",
|
||||
"3355": "I like purple.",
|
||||
"3356": "I like pink.",
|
||||
"3357": "I like white.",
|
||||
"3358": "I like black.",
|
||||
"3359": "I like silver.",
|
||||
"3360": "I like gold.",
|
||||
"3450": "I like popsicles.",
|
||||
"3451": "I like pizza.",
|
||||
"3452": "I like hamburgers.",
|
||||
"3453": "I like veggies.",
|
||||
"3455": "I like spaghetti.",
|
||||
"4356": "I like candy.",
|
||||
"3457": "I like ice cream.",
|
||||
"3458": "I like peanut butter.",
|
||||
"3459": "I like cookies.",
|
||||
"4550": "I like to rock out.",
|
||||
"4551": "I like all music.",
|
||||
"4552": "I like hip hop music.",
|
||||
"4553": "I like country music.",
|
||||
"4554": "I like classical music.",
|
||||
"4555": "I like techno music.",
|
||||
"4557": "I like jazz music",
|
||||
"4558": "I like blues music.",
|
||||
"4559": "I like rock music.",
|
||||
"4650": "I live near the ocean.",
|
||||
"4651": "I live in the desert.",
|
||||
"4652": "I live in the city.",
|
||||
"4653": "I live on a farm.",
|
||||
"4654": "I live in a tree house.",
|
||||
"4655": "I live in outer space.",
|
||||
"4656": "I live in the jungle.",
|
||||
"4657": "I live on a boat.",
|
||||
"4658": "I live on an island.",
|
||||
"4750": "Let's dance!",
|
||||
"4751": "Let's race!",
|
||||
"4752": "Let's hang out!",
|
||||
"4753": "Let's chill!",
|
||||
"4754": "Add me as a friend.",
|
||||
"4755": "Look at that!",
|
||||
"4756": "I am lost.",
|
||||
"4757": "I don't know what to do.",
|
||||
"4758": "Ready...set...go!",
|
||||
"4860": {
|
||||
"04000000": "I am going to change my car.",
|
||||
"0": "I am going to change clothes."
|
||||
},
|
||||
"1564": {
|
||||
"04000000": "I am going to race.",
|
||||
"0": "I am going to dance."
|
||||
},
|
||||
"4862": {
|
||||
"04000000": "I am going to buy parts.",
|
||||
"0": "I am going to buy clothes."
|
||||
},
|
||||
"4863": {
|
||||
"04000000": "I am going to get Street Cred.",
|
||||
"0": "I am going to get Style Points."
|
||||
},
|
||||
"4864": "I am going to hang out.",
|
||||
"5050": "Where are you going?",
|
||||
"5051": "What do you like to do?",
|
||||
"5052": "What should we do?",
|
||||
"5053": "Will you follow me?",
|
||||
"5054": "Will you show me your favorite place?",
|
||||
"5056": "Want to be my friend?",
|
||||
"5057": {
|
||||
"04000000": "Want to race?",
|
||||
"0": "Want to dance?"
|
||||
},
|
||||
"5059": "Want to explore?",
|
||||
"5250": "What is your favorite animal?",
|
||||
"5251": "What is your favorite color?",
|
||||
"5252": "What is your favorite food?",
|
||||
"5253": "What type of music do you like?",
|
||||
"5255": "What did you say?",
|
||||
"6050": "Haha!",
|
||||
"6051": "Hehe!",
|
||||
"6052": "Bwa-ha-ha-ha!",
|
||||
"6150": "Woof!",
|
||||
"6151": "Meow!",
|
||||
"6152": "Quack!",
|
||||
"6153": "Roar!",
|
||||
"6154": "Ribbit!",
|
||||
"6350": "LOL",
|
||||
"6351": "BFF",
|
||||
"6352": "JK",
|
||||
"6353": "IDK",
|
||||
"6354": "PLZ",
|
||||
"6355": "THX",
|
||||
"6356": "BRB",
|
||||
"6357": "CYA",
|
||||
"6358": "TTYL",
|
||||
"6550": "Stop that!",
|
||||
"6551": "Please do not do that.",
|
||||
"6552": "Go away!",
|
||||
"6553": "That is not very nice.",
|
||||
"6554": "You are in my personal bubble.",
|
||||
"6555": "Hurry up!",
|
||||
"6556": "Wait for me!",
|
||||
"6557": "Please slow down.",
|
||||
"6650": "Wow!",
|
||||
"6651": "That was awesome!",
|
||||
"6652": "Super cool!",
|
||||
"6653": "I'm glad you are here.",
|
||||
"6750": "You are awesome!",
|
||||
"6751": "You are funny!",
|
||||
"6752": "You are pretty.",
|
||||
"6753": "You are handsome.",
|
||||
"6754": "You are stunning.",
|
||||
"6755": "You are crazy.",
|
||||
"6756": "You are cool.",
|
||||
"6757": "You are great.",
|
||||
"6758": "You are goofy.",
|
||||
"6759": "You are one of a kind.",
|
||||
"6760": "You are my best friend.",
|
||||
"6850": "Thanks!",
|
||||
"6851": "Thank you!",
|
||||
"6852": "Thanks a bunch!",
|
||||
"6853": "Thanks for being my friend.",
|
||||
"6854": "Thanks for showing me that.",
|
||||
"6855": "You're welcome.",
|
||||
"6856": "No problem!",
|
||||
"6857": "Anytime.",
|
||||
"6950": "Sorry!",
|
||||
"6951": "Oops, sorry!",
|
||||
"6952": "Sorry, I have to go.",
|
||||
"6953": "Sorry, I am busy.",
|
||||
"6954": "Sorry, I didn't mean that.",
|
||||
"6955": "I take it back.",
|
||||
"6956": "It's okay.",
|
||||
"6957": "Don't worry about it.",
|
||||
"6958": "I forgive you.",
|
||||
"7050": "Yes.",
|
||||
"7051": "No.",
|
||||
"7052": "Maybe.",
|
||||
"7053": "Follow me.",
|
||||
"7054": "Me too.",
|
||||
"14000": "Good evening",
|
||||
"30100": "I am a mythie trainer.",
|
||||
"30206": "I am a level 7.",
|
||||
"30207": "I am a level 8.",
|
||||
"30208": "I am a level 9.",
|
||||
"30209": "I am a level 10.",
|
||||
"31006": "I like to train mythies.",
|
||||
"31007": "I like to earn coins.",
|
||||
"31008": "I like to buy new pets.",
|
||||
"31009": "I like to buy new rides.",
|
||||
"31061": "I like the Amphitheatre.",
|
||||
"31062": "I like the Stadium.",
|
||||
"31100": "I like all of my mythies.",
|
||||
"31101": "I like training my mythies.",
|
||||
"31102": "I like when my mythies are babies.",
|
||||
"31103": "I like when my mythies are learning to fly.",
|
||||
"31104": "I like when my mythies are grown up.",
|
||||
"31105": "I like seeing all the different mythies.",
|
||||
"31209": "I like mythies.",
|
||||
"33001": "I would be a famous lion.",
|
||||
"33002": "I would be a hilarious zebra.",
|
||||
"33003": "I would be a fabulous hippo.",
|
||||
"33004": "I would be an anxious giraffe.",
|
||||
"33005": "I would be an adventurous penguin.",
|
||||
"33006": "I would be a soaring lemur.",
|
||||
"33007": "I would be a curious chimp.",
|
||||
"40006": "Let's have a party!",
|
||||
"41054": "I am going to get JumpStars.",
|
||||
"41055": "I am going to see my mythie.",
|
||||
"41056": "I am going to decorate my house.",
|
||||
"41057": "I am going to play arcade games.",
|
||||
"41058": "I am going to buy a pet.",
|
||||
"50007": "Have you seen any Punk Punks?",
|
||||
"51002": "Want to be my neighbor?",
|
||||
"51003": "Want to see my house?",
|
||||
"71003": "I like your pet.",
|
||||
"71004": "I like your ride.",
|
||||
"71007": "I like your shirt.",
|
||||
"863": "I am a princess",
|
||||
"864": "I am a fashion designer.",
|
||||
"866": "I am a diva.",
|
||||
"867": "I am a shopaholic.",
|
||||
"954": "I like to shop.",
|
||||
"3052": "I like to go to the mall.",
|
||||
"3054": "I like to go to school dances.",
|
||||
"4850": "I am going to play Rodeo Racing",
|
||||
"4851": "I am going to Dance Off",
|
||||
"4852": "I am going to play Fashion Show.",
|
||||
"4853": "I am going to the Enchanted Sanctuary",
|
||||
"5058": "Want to race at Rodeo Racing?",
|
||||
"6250": "Girl, you're rockin that outfit!",
|
||||
"6251": "That Rocks!",
|
||||
"6252": "That is soo cute!",
|
||||
"6253": "You go girlfriend!",
|
||||
"6254": "I love your style!",
|
||||
"6255": "That's adorable",
|
||||
"6256": "The whole look is fierce!",
|
||||
"6257": "Like, totally!",
|
||||
"6258": "Awesome!",
|
||||
"6259": "You're so sweet!",
|
||||
"6260": "Chill!",
|
||||
"6261": "Dun dun dun...",
|
||||
"6262": "Mojo no no!",
|
||||
"6263": "Are you serious?!",
|
||||
"6264": "Sweet!",
|
||||
"6265": "La-di-da!",
|
||||
"6266": "Kersplat!",
|
||||
"6267": "Achoo!",
|
||||
"6654": "I like your style.",
|
||||
"6655": "I like your look.",
|
||||
"6656": "I like your name.",
|
||||
"6657": "I like your hair.",
|
||||
"6658": "I like your mouth.",
|
||||
"6659": "I like your shoes.",
|
||||
"6660": "I like your eyes.",
|
||||
"6761": "You are lovely darling."
|
||||
}
|
||||
}
|
@ -21,5 +21,8 @@
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="emote_data.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
Loading…
x
Reference in New Issue
Block a user