-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(rdr): add UiFeed structs & native usages
- Loading branch information
1 parent
72755cb
commit 314ecfe
Showing
2 changed files
with
350 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
using System.Security; | ||
using CitizenFX.RedM.Native; | ||
|
||
namespace CitizenFX.RedM | ||
{ | ||
public static class UiFeed | ||
{ | ||
// a lot of feed natives reuse the same general structure with just different argument count so we just define | ||
// these two and reuse them | ||
[SecuritySafeCritical] | ||
private static int GenerateFeed4Args(Hash nativeHash, UiFeedInfo feedInfo, UiFeedData feedData, bool bUnk1 = true, bool bUnk2 = true) | ||
{ | ||
int retVal; | ||
unsafe | ||
{ | ||
UnsafeUiInfo dur = new UnsafeUiInfo(feedInfo); | ||
UnsafeUiFeedNotification notification = new UnsafeUiFeedNotification(feedData); | ||
retVal = Natives.Call<int>(nativeHash, &dur, ¬ification, bUnk1, bUnk2); | ||
} | ||
return retVal; | ||
} | ||
|
||
[SecuritySafeCritical] | ||
private static int GenerateFeed3Args(Hash nativeHash, UiFeedInfo feedInfo, UiFeedData feedData, bool bUnk1 = true) | ||
{ | ||
int retVal; | ||
unsafe | ||
{ | ||
UnsafeUiInfo dur = new UnsafeUiInfo(feedInfo); | ||
UnsafeUiFeedNotification notification = new UnsafeUiFeedNotification(feedData); | ||
retVal = Natives.Call<int>(nativeHash, &dur, ¬ification, bUnk1); | ||
} | ||
return retVal; | ||
} | ||
|
||
/// <summary> | ||
/// Places the first <paramref name="feedData" /> varString onto the kill feed. | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int FeedTicker(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed3Args(Hash._UI_FEED_POST_FEED_TICKER, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int GameUpdateShard(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed3Args(Hash._UI_FEED_POST_GAME_UPDATE_SHARD, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// Places the first <paramref name="feedData" /> varString as a simple notification on the top left of the screen. | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int HelpText(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed3Args(Hash._UI_FEED_POST_HELP_TEXT, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// Displays the first <paramref name="feedData" /> varString as a location in the bottom left of the screen | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int MissionName(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed3Args(Hash._UI_FEED_POST_MISSION_NAME, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// Displays the first <paramref name="feedData" /> varString as a subtitle in the bottom of the screen | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int Objective(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed3Args(Hash._UI_FEED_POST_OBJECTIVE, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int OneTextShard(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed3Args(Hash._UI_FEED_POST_ONE_TEXT_SHARD, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// Displays the <paramref name="feedData" /> as a <see cref="UiFeed.SampleToast" /> | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int RankupToast(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed3Args(Hash._UI_FEED_POST_RANKUP_TOAST, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// Displays the first <paramref name="feedData" /> as a message at the center of the screen. | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int ReticleMessage(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed3Args(Hash._UI_FEED_POST_RETICLE_MESSAGE, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// Displays the <paramref name="feedInfo"/> as a notification in the top left. | ||
/// This notification is similar to <see cref="UiFeed.SampleToast" /> but it will not display the color, and | ||
/// varString2 will disappear before the notification finishes. | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int SampleNotification(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed4Args(Hash._UI_FEED_POST_SAMPLE_NOTIFICATION, feedInfo, feedData); | ||
} | ||
|
||
|
||
/// <summary> | ||
/// Displays the <paramref name="feedInfo" /> as a notification in the top left with the specified icon and color. | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int SampleToast(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed4Args(Hash._UI_FEED_POST_SAMPLE_TOAST, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// Displays the <paramref name="feedInfo" /> as a simple notification on the right above the kill feed. | ||
/// This will use whatever is in <see cref="UiFeed" />s icon field as the color | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int SampleToastRight(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed3Args(Hash._UI_FEED_POST_SAMPLE_TOAST_RIGHT, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int ToastWithAppLink(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed3Args(Hash._UI_FEED_POST_SAMPLE_TOAST_WITH_APP_LINK, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int ThreeTextShard(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed4Args(Hash._UI_FEED_POST_THREE_TEXT_SHARD, feedInfo, feedData); | ||
} | ||
|
||
|
||
/// <summary> | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int TwoTextShard(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed4Args(Hash._UI_FEED_POST_TWO_TEXT_SHARD, feedInfo, feedData); | ||
} | ||
|
||
/// <summary> | ||
/// Displays the <paramref name="feedInfo" /> as a microphone notification on the right side of the screen | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int VoiceChatFeed(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed3Args(Hash._UI_FEED_POST_VOICE_CHAT_FEED, feedInfo, feedData); | ||
} | ||
|
||
|
||
/// <summary> | ||
/// Displays the <paramref name="feedInfo" /> as a microphone notification on the right side of the screen | ||
/// </summary> | ||
/// <returns>Returns a feedId that can be used by <see cref="UiFeed.ClearFeedByFeedId"/> to remove the feed</returns> | ||
public static int LocationShard(UiFeedInfo feedInfo, UiFeedData feedData) | ||
{ | ||
return GenerateFeed4Args(Hash._UI_FEED_POST_LOCATION_SHARD, feedInfo, feedData, false, true); | ||
} | ||
|
||
/// <summary> | ||
/// Removes the specified <paramref name="feedId" /> from the feed. | ||
/// </summary> | ||
public static void ClearFeedByFeedId(int feedId) | ||
{ | ||
Natives.UiFeedClearHelpTextFeed(feedId, false); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
using System.Security; | ||
using CitizenFX.Core; | ||
using CitizenFX.Core.Native; | ||
using CitizenFX.RedM.Native; | ||
|
||
namespace CitizenFX.RedM | ||
{ | ||
public struct UiFeedInfo { | ||
internal Int64 m_duration; | ||
internal IntPtr m_varString1; | ||
internal IntPtr m_varString2; | ||
|
||
public UiFeedInfo(Int64 dur) { | ||
m_duration = dur; | ||
m_varString1 = IntPtr.Zero; | ||
m_varString2 = IntPtr.Zero; | ||
} | ||
|
||
public UiFeedInfo(Int64 dur, VarString varString1, VarString? varString2) | ||
{ | ||
m_duration = dur; | ||
m_varString1 = varString1.m_varStringPtr; | ||
m_varString2 = varString2?.m_varStringPtr ?? IntPtr.Zero; | ||
} | ||
}; | ||
|
||
[StructLayout(LayoutKind.Explicit, Size = 0x68)] | ||
[SecuritySafeCritical] | ||
internal unsafe struct UnsafeUiInfo | ||
{ | ||
[FieldOffset(0x00)] private Int64 m_duration; | ||
|
||
[FieldOffset(0x08)] private IntPtr m_unk1; | ||
|
||
[FieldOffset(0x10)] private IntPtr m_unk2; | ||
|
||
[FieldOffset(0x18)] private Int64 m_unk3; | ||
|
||
[FieldOffset(0x20)] private Int64 m_unk4; | ||
|
||
[FieldOffset(0x28)] private Int64 m_unk5; | ||
|
||
[FieldOffset(0x30)] private IntPtr m_unk6; | ||
|
||
[FieldOffset(0x38)] private Int64 m_unk7; | ||
|
||
[FieldOffset(0x40)] private Int64 m_unk8; | ||
|
||
[FieldOffset(0x48)] private Int64 m_unk9; | ||
|
||
[FieldOffset(0x50)] private Int64 m_unk10; | ||
|
||
[FieldOffset(0x58)] private Int64 m_unk11; | ||
|
||
[FieldOffset(0x60)] private Int64 m_unk12; | ||
|
||
public UnsafeUiInfo(UiFeedInfo feedInfo) { | ||
m_duration = feedInfo.m_duration; | ||
m_unk1 = IntPtr.Zero; | ||
m_unk2 = IntPtr.Zero; | ||
m_unk3 = 0; | ||
m_unk4 = 0; | ||
m_unk5 = 0; | ||
m_unk6 = IntPtr.Zero; | ||
m_unk7 = 0; | ||
m_unk8 = 0; | ||
m_unk9 = 0; | ||
m_unk10 = 0; | ||
m_unk11 = 0; | ||
m_unk12 = 0; | ||
} | ||
} | ||
|
||
public struct ColorString | ||
{ | ||
internal CString m_colorString; | ||
public ColorString(int rgb) | ||
{ | ||
m_colorString = Natives.CreateColorString(rgb); | ||
} | ||
} | ||
|
||
public struct VarString | ||
{ | ||
internal IntPtr m_varStringPtr; | ||
public VarString(params Argument[] arguments) | ||
{ | ||
m_varStringPtr = Natives.Call<IntPtr>(Hash.VAR_STRING, arguments); | ||
} | ||
} | ||
|
||
public struct UiFeedData | ||
{ | ||
internal VarString m_varString1; | ||
internal CString m_string2; | ||
internal VarString? m_varString2; | ||
internal uint m_iconDict; | ||
internal uint m_icon; | ||
internal uint m_color; | ||
|
||
public UiFeedData(VarString varStr1, VarString? varStr2, string iconDict = null, string icon = null, string color = null) | ||
{ | ||
m_varString1 = varStr1; | ||
m_string2 = null; | ||
m_varString2 = varStr2; | ||
m_iconDict = Game.GenerateHash(iconDict); | ||
m_icon = Game.GenerateHash(icon); | ||
m_color = Game.GenerateHash(color); | ||
} | ||
|
||
public UiFeedData(VarString varStr1, CString str, string iconDict = null, string icon = null, string color = null) | ||
{ | ||
m_varString1 = varStr1; | ||
m_string2 = str; | ||
m_varString2 = null; | ||
m_iconDict = Game.GenerateHash(iconDict); | ||
m_icon = Game.GenerateHash(icon); | ||
m_color = Game.GenerateHash(color); | ||
} | ||
} | ||
|
||
|
||
[StructLayout(LayoutKind.Explicit, Size = 0x40)] | ||
[SecuritySafeCritical] | ||
internal unsafe struct UnsafeUiFeedNotification | ||
{ | ||
[FieldOffset(0x00)] Int64 unk1; | ||
|
||
[FieldOffset(0x08)] char* varStringPtr1; | ||
|
||
[FieldOffset(0x10)] char* varStringPtr2; | ||
|
||
[FieldOffset(0x18)] Int64 unk2; | ||
|
||
[FieldOffset(0x20)] UInt64 iconDictHash; | ||
|
||
[FieldOffset(0x28)] UInt64 iconHash; | ||
|
||
[FieldOffset(0x30)] UInt64 colorHash; | ||
|
||
[FieldOffset(0x38)] Int64 unk3; | ||
|
||
public UnsafeUiFeedNotification(UiFeedData fd) { | ||
unk1 = 0; | ||
varStringPtr1 = (char*)fd.m_varString1.m_varStringPtr; | ||
if (fd.m_string2 != null) { | ||
var str = fd.m_string2.GetPinnableReference(); | ||
varStringPtr2 = (char*)str; | ||
} else { | ||
varStringPtr2 = (char*)(fd.m_varString2?.m_varStringPtr ?? IntPtr.Zero); | ||
} | ||
unk2 = 0; | ||
iconDictHash = fd.m_iconDict; | ||
iconHash = fd.m_icon; | ||
colorHash = fd.m_color; | ||
unk3 = 0; | ||
} | ||
} | ||
} |