mirror of
https://github.com/RaindropViewer/RaindropViewer.git
synced 2026-07-31 03:22:14 +00:00
222 lines
7.4 KiB
C#
222 lines
7.4 KiB
C#
/**
|
|
* Radegast Metaverse Client
|
|
* Copyright(c) 2009-2014, Radegast Development Team
|
|
* Copyright(c) 2016-2020, Sjofn, LLC
|
|
* All rights reserved.
|
|
*
|
|
* Radegast is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program.If not, see<https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using OpenMetaverse;
|
|
using OpenMetaverse.Assets;
|
|
using Plugins.CommonDependencies;
|
|
|
|
namespace Raindrop.Core
|
|
{
|
|
public class GestureManager
|
|
{
|
|
private class GestureTrigger
|
|
{
|
|
public string TriggerLower { get; set; }
|
|
public string Replacement { get; set; }
|
|
public UUID AssetID { get; set; }
|
|
}
|
|
|
|
/// <summary>Gesture manager instance</summary>
|
|
public static GestureManager Instance { get; } = new GestureManager();
|
|
|
|
private Dictionary<UUID, GestureTrigger> Gestures { get; } = new Dictionary<UUID, GestureTrigger>();
|
|
private Random Random { get; } = new Random();
|
|
|
|
/// <summary>
|
|
/// Begins monitoring for changes in gestures.
|
|
/// </summary>
|
|
public void BeginMonitoring()
|
|
{
|
|
var client = RaindropInstance.GlobalInstance.Client;
|
|
client.Inventory.Store.InventoryObjectAdded += Store_InventoryObjectAdded;
|
|
client.Inventory.Store.InventoryObjectUpdated += Store_InventoryObjectUpdated;
|
|
|
|
foreach (var item in client.Inventory.Store.Items)
|
|
{
|
|
var gesture = item.Value.Data as InventoryGesture;
|
|
if (gesture == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
UpdateInventoryGesture(gesture);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops monitoring for changes in gestures.
|
|
/// </summary>
|
|
public void StopMonitoring()
|
|
{
|
|
var client = RaindropInstance.GlobalInstance.Client;
|
|
client.Inventory.Store.InventoryObjectAdded -= Store_InventoryObjectAdded;
|
|
client.Inventory.Store.InventoryObjectUpdated -= Store_InventoryObjectUpdated;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processes a chat message and activates a gesture if a gesture trigger is present.
|
|
/// </summary>
|
|
/// <param name="message">Message to process</param>
|
|
/// <returns>New message after gesture has been triggered and trigger word has been replaced</returns>
|
|
public string PreProcessChatMessage(string message)
|
|
{
|
|
var outString = new StringBuilder(message.Length);
|
|
var words = message.Split(' ');
|
|
var gestureWasTriggered = false;
|
|
|
|
foreach (var word in words)
|
|
{
|
|
if (gestureWasTriggered)
|
|
{
|
|
outString.Append(word);
|
|
outString.Append(' ');
|
|
}
|
|
else
|
|
{
|
|
gestureWasTriggered = ProcessWord(word, outString);
|
|
}
|
|
}
|
|
|
|
// Remove trailing space that was added above at the end of our new sentence
|
|
if (outString.Length > 0 && outString[outString.Length - 1] == ' ')
|
|
{
|
|
outString.Remove(outString.Length - 1, 1);
|
|
}
|
|
|
|
return outString.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks a single word for a gesture trigger and appends the final word to the output
|
|
/// </summary>
|
|
/// <param name="word">Word to check for gesture triggers</param>
|
|
/// <param name="outString">Where to output the word or replacement word to</param>
|
|
/// <returns>True if a gesture trigger was executed.</returns>
|
|
private bool ProcessWord(string word, StringBuilder outString)
|
|
{
|
|
var possibleTriggers = new List<GestureTrigger>();
|
|
var client = RaindropInstance.GlobalInstance.Client;
|
|
var lowerWord = word.ToLower();
|
|
|
|
client.Self.ActiveGestures.ForEach(pair =>
|
|
{
|
|
var activeGestureID = pair.Key;
|
|
if (!Gestures.ContainsKey(activeGestureID))
|
|
{
|
|
return;
|
|
}
|
|
var gesture = Gestures[activeGestureID];
|
|
|
|
if (lowerWord != gesture.TriggerLower)
|
|
{
|
|
return;
|
|
}
|
|
|
|
possibleTriggers.Add(gesture);
|
|
});
|
|
|
|
if (possibleTriggers.Count == 0)
|
|
{
|
|
outString.Append(word);
|
|
outString.Append(' ');
|
|
return false;
|
|
}
|
|
|
|
GestureTrigger gestureToPlay;
|
|
if (possibleTriggers.Count > 1)
|
|
{
|
|
var gestureIndexToPlay = Random.Next(possibleTriggers.Count);
|
|
gestureToPlay = possibleTriggers[gestureIndexToPlay];
|
|
}
|
|
else
|
|
{
|
|
gestureToPlay = possibleTriggers[0];
|
|
}
|
|
|
|
client.Self.PlayGesture(gestureToPlay.AssetID);
|
|
|
|
if (!String.IsNullOrEmpty(gestureToPlay.Replacement))
|
|
{
|
|
outString.Append(gestureToPlay.Replacement);
|
|
outString.Append(' ');
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles any addition or update to gesture items in the inventory.
|
|
/// </summary>
|
|
/// <param name="gesture">Gesture that was added or updated.</param>
|
|
private void UpdateInventoryGesture(InventoryGesture gesture)
|
|
{
|
|
var client = RaindropInstance.GlobalInstance.Client;
|
|
|
|
client.Assets.RequestAsset(gesture.AssetUUID, AssetType.Gesture, false, (_, asset) =>
|
|
{
|
|
if (!(asset is AssetGesture assetGesture))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!assetGesture.Decode())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!Gestures.ContainsKey(gesture.UUID))
|
|
{
|
|
Gestures.Add(gesture.UUID, new GestureTrigger());
|
|
}
|
|
|
|
if (Gestures.TryGetValue(gesture.UUID, out var existingGestureTrigger))
|
|
{
|
|
existingGestureTrigger.TriggerLower = assetGesture.Trigger.ToLower();
|
|
existingGestureTrigger.Replacement = assetGesture.ReplaceWith;
|
|
existingGestureTrigger.AssetID = assetGesture.AssetID;
|
|
}
|
|
});
|
|
}
|
|
|
|
private void Store_InventoryObjectUpdated(object sender, InventoryObjectUpdatedEventArgs e)
|
|
{
|
|
if (!(e.NewObject is InventoryGesture gesture))
|
|
{
|
|
return;
|
|
}
|
|
|
|
UpdateInventoryGesture(gesture);
|
|
}
|
|
|
|
private void Store_InventoryObjectAdded(object sender, InventoryObjectAddedEventArgs e)
|
|
{
|
|
if (!(e.Obj is InventoryGesture gesture))
|
|
{
|
|
return;
|
|
}
|
|
|
|
UpdateInventoryGesture(gesture);
|
|
}
|
|
}
|
|
}
|