I have problem share to facebook from android use unity C#.
When I try, when debug, it's always need user access token to share, and when share it's just share to tester and admin.
When I try on device it's just show "this application will be access to your email ..." and after that nothing happened.
This is my code:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Facebook;
public class PTShare : MonoBehaviour {
private string lastResponse = "";
public OTSprite shareBtn;
// Use this for initialization
void Awake () {
CallFBInit ();
}
void Start () {
shareBtn = GameObject.Find ("share").GetComponent<OTSprite>();
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (0)) {
if(OT.Over(shareBtn)) {
FB.Login("email,publish_actions", LoginCallback);
CallFBFeed();
}
}
}
public static IEnumerator GetAppAccessToken() {
//Debug.Log("asking FB for App AccessToken");
string url = string.Format("https://graph.facebook.com/oauth/access_token?grant_type=client_credentials&client_ id={0}&client_secret={1}",
"1443575049241638",
"efde01d85ba62e4d81708b4189419d5c");
WWW fbRequest = new WWW(url);
// Wait for download to complete
yield return fbRequest;
string accessToken = fbRequest.text;
Debug.Log("got token: " + accessToken);
accessToken = accessToken.Substring(accessToken.IndexOf("=") + 1);
Debug.Log("trimmed token: " + accessToken);
//FB.UserId = accessToken;
return true;
}
public string FeedToId = "";
public string FeedLink = "http://gambrenggames.com/game-detail/junes-potion/2";
public string FeedLinkName = "June's Potion";
public string FeedLinkCaption = "I play June's Potion friends! Can you play it?";
public string FeedLinkDescription = "";
public string FeedPicture = "http://gambrenggames.com/website/images/game-icon/05540225032014.png";
public string FeedMediaSource = "";
public string FeedActionName = "";
public string FeedActionLink = "";
public string FeedReference = "";
public bool IncludeFeedProperties = false;
private Dictionary<string, string[]> FeedProperties = new Dictionary<string, string[]>();
private void CallFBFeed()
{
Dictionary<string, string[]> feedProperties = null;
if (IncludeFeedProperties)
{
feedProperties = FeedProperties;
}
FB.Feed(
toId: FeedToId,
link: FeedLink,
linkName: FeedLinkName,
linkCaption: FeedLinkCaption,
linkDescription: FeedLinkDescription,
picture: FeedPicture,
mediaSource: FeedMediaSource,
actionName: FeedActionName,
actionLink: FeedActionLink,
reference: FeedReference,
properties: feedProperties,
callback: Callback
);
}
private Texture2D lastResponseTexture;
public string ApiQuery = "";
void Callback(FBResult result)
{
lastResponseTexture = null;
// Some platforms return the empty string instead of null.
if (!String.IsNullOrEmpty(result.Error))
lastResponse = "Error Response:\n" + result.Error;
else if (!ApiQuery.Contains("/picture"))
lastResponse = "Success Response:\n" + result.Text;
else
{
lastResponseTexture = result.Texture;
lastResponse = "Success Response:\n";
}
}
private bool isInit = false;
private void CallFBInit()
{
FB.Init(OnInitComplete, OnHideUnity);
}
private void OnInitComplete()
{
Debug.Log("FB.Init completed: Is user logged in? " + FB.IsLoggedIn);
isInit = true;
}
private void OnHideUnity(bool isGameShown)
{
Debug.Log("Is game showing? " + isGameShown);
}
private void CallFBLogin()
{
FB.Login("email,publish_actions", LoginCallback);
}
void LoginCallback(FBResult result)
{
if (result.Error != null)
lastResponse = "Error Response:\n" + result.Error;
else if (!FB.IsLoggedIn)
{
lastResponse = "Login cancelled by Player";
}
else
{
lastResponse = "Login was successful!";
}
}
private void CallFBLogout()
{
FB.Logout();
}
}
FB.Login is async method and FB.Feed (maybe?) requires Login.
So try call CallFBFeed(); inside LoginCallback method. Like that:
void Update () {
if (Input.GetMouseButtonDown (0)) {
if(OT.Over(shareBtn)) {
if (FB.IsLoggedIn)
{
CallFBFeed();
}
else
{
FB.Login("email,publish_actions", LoginCallback);
}
}
}
}
void LoginCallback(FBResult result)
{
if (result.Error != null)
lastResponse = "Error Response:\n" + result.Error;
else if (!FB.IsLoggedIn)
{
lastResponse = "Login cancelled by Player";
}
else
{
lastResponse = "Login was successful!";
CallFBFeed();
}
}
But it can be problem with android device (i had "magic" with fb login on some old devices) or settings and your code is ok
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 months ago.
Improve this question
Here are the errors.
I am creating a firebase login and sign up unity project.
I have commented some of the lines because I havent programmed it yet. I am following this tutorial : https://www.youtube.com/watch?v=9-ZS7-I_CfQ
I have 2 scripts, firebaseManager and authUI manager.
Here is my firebaseManager script:
using UnityEngine;
using System.Collections;
using Firebase;
using Firebase.Auth;
using TMPro;
public class FirebaseManager : MonoBehaviour
{
public static FirebaseManager instance;
[Header("Firebase")]
public FirebaseAuth auth;
public FirebaseUser user;
[Space(5f)]
[Header("Login References")]
[SerializeField]
private TMP_InputField loginEmail;
[SerializeField]
private TMP_InputField loginPassword;
[SerializeField]
private TMP_Text loginOutputText;
[Space(5f)]
[Header("Register References")]
[SerializeField]
private TMP_InputField registerUsername;
[SerializeField]
private TMP_InputField registerEmail;
[SerializeField]
private TMP_InputField registerPassword;
[SerializeField]
private TMP_InputField registerConfirmPassword;
[SerializeField]
private TMP_Text registerOutputText;
private void Awake()
{
DontDestroyOnLoad(gameObject);
if (instance == null)
{
instance = this;
}
else if (instance != this)
{
Destroy(instance.gameObject);
instance = this;
}
}
private void Start()
{
StartCoroutine(CheckAndFixDependancies());
}
private IEnumerator CheckAndFixDependancies()
{
var checkAndFixDependanciesTask = FirebaseApp.CheckAndFixDependenciesAsync();
yield return new WaitUntil(predicate: () => checkAndFixDependanciesTask.IsCompleted);
var dependancyResult = checkAndFixDependanciesTask.Result;
if (dependancyResult == DependencyStatus.Available)
{
InitializeFirebase();
}
else
{
Debug.LogError($"Could not resolve all firebase dependancies: {dependancyResult}");
}
}
private void InitializeFirebase()
{
auth = FirebaseAuth.DefaultInstance;
StartCoroutine(CheckAutoLogin());
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
private IEnumerator CheckAutoLogin()
{
yield return new WaitForEndOfFrame();
if (user != null)
{
var reloadUserTask = user.ReloadAsync();
yield return new WaitUntil(predicate: () => reloadUserTask.IsCompleted);
AutoLogin();
}
else
{
AuthUIManager.instance.LoginScreen();
}
}
private void AutoLogin()
{
if (user != null)
{
if (user.IsEmailVerified)
{
GameManager.instance.ChangeScene(1);
}
else
{
StartCoroutine(SendVerificationEmail());
}
}
else
{
AuthUIManager.instance.LoginScreen();
}
}
private void AuthStateChanged(object sender, System.EventArgs eventArgs)
{
if (auth.CurrentUser != user)
{
bool signedIn = user != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && user != null)
{
Debug.Log("Signed Out");
// Write signed out user code here
}
user = auth.CurrentUser;
if (signedIn)
{
Debug.Log($"Signed In: {user.DisplayName}");
}
}
}
public void ClearOutputs()
{
loginOutputText.text = "";
registerOutputText.text = "";
}
public void LoginButton()
{
StartCoroutine(LoginLogic(loginEmail.text, loginPassword.text));
}
public void RegisterButton()
{
StartCoroutine(RegisterLogic(registerUsername.text, registerEmail.text, registerPassword.text, registerConfirmPassword.text));
}
private IEnumerator LoginLogic(string _email, string _password)
{
Credential credential = EmailAuthProvider.GetCredential(_email, _password);
var loginTask = auth.SignInWithCredentialAsync(credential);
yield return new WaitUntil(predicate: () => loginTask.IsCompleted);
if (loginTask.Exception != null)
{
FirebaseException firebaseException = (FirebaseException)loginTask.Exception.GetBaseException();
AuthError error = (AuthError)firebaseException.ErrorCode;
string output = "Unknown Error, Please Try Again";
switch (error)
{
case AuthError.MissingEmail:
output = "Please Enter Your Email";
break;
case AuthError.MissingPassword:
output = "Please Enter Your Password";
break;
case AuthError.InvalidEmail:
output = "Invalid Email";
break;
case AuthError.WrongPassword:
output = "Incorrect Password";
break;
case AuthError.UserNotFound:
output = "Account Does Not Exist";
break;
}
loginOutputText.text = output;
}
else
{
if (user.IsEmailVerified)
{
yield return new WaitForSeconds(1f);
GameManager.instance.ChangeScene(1);
}
else
{
StartCoroutine(SendVerificationEmail());
}
}
}
private IEnumerator RegisterLogic(string _username, string _email, string _password, string _confirmPassword)
{
if (_username == "")
{
registerOutputText.text = "Please Enter A Username";
}
else if (_password != _confirmPassword)
{
registerOutputText.text = "Passwords Do Not Match!";
}
// else if (_username.ToLower() == "bad word")
// {
// registerOutputText.text = "That Username Is Innapropriate";
// }
else
{
var registerTask = auth.CreateUserWithEmailAndPasswordAsync(_email, _password);
yield return new WaitUntil(predicate: () => registerTask.IsCompleted);
if (registerTask.Exception != null)
{
FirebaseException firebaseException = (FirebaseException)registerTask.Exception.GetBaseException();
AuthError error = (AuthError)firebaseException.ErrorCode;
string output = "Unknown Error, Please Try Again";
switch (error)
{
case AuthError.InvalidEmail:
output = "Invalid Email";
break;
case AuthError.EmailAlreadyInUse:
output = "Email Is Already In Use";
break;
case AuthError.WeakPassword:
output = "Weak Password. Please include capital letters, numbers and special symbols.";
break;
case AuthError.MissingEmail:
output = "Please Enter Your Email";
break;
case AuthError.MissingPassword:
output = "Please Enter Your Password";
break;
}
registerOutputText.text = output;
}
else
{
UserProfile profile = new UserProfile
{
DisplayName = _username,
PhotoUrl = new System.Uri("https://t4.ftcdn.net/jpg/02/29/75/83/360_F_229758328_7x8jwCwjtBMmC6rgFzLFhZoEpLobB6L8.jpg");
};
var defaultUserTask = user.UpdateUserProfileAsync(profile);
yield return new WaitUntil(predicate: () => defaultUserTask.IsCompleted);
if (defaultUserTask.Exception != null)
{
user.DeleteAsync();
FirebaseException firebaseException = (FirebaseException)defaultUserTask.Exception.GetBaseException();
AuthError error = (AuthError)firebaseException.ErrorCode;
string output = "Unknown Error, Please Try Again";
switch (error)
{
case AuthError.Cancelled:
output = "Update User Cancelled";
break;
case AuthError.SessionExpired:
output = "Session Expired";
break;
}
registerOutputText.text = output;
}
else
{
Debug.Log($"Firebase User Created Successfuly: {user.DisplayName} ({user.UserId})");
StartCoroutine(SendVerificationEmail());
}
}
}
}
private IEnumerator SendVerificationEmail()
{
if (user != null)
{
var emailTask = user.SendEmailVerificationAsync();
yield return new WaitUntil(predicate: () => emailTask.IsCompleted);
if (emailTask.Exception != null)
{
FirebaseException firebaseException = (FirebaseException)emailTask.Exception.GetBaseException();
AuthError error = (AuthError)firebaseException.ErrorCode;
string output = "Unkown Error, Try Again!";
switch (error)
{
case AuthError.Cancelled:
output = "Verification Task Was Cancelled";
break;
case AuthError.InvalidRecipientEmail:
output = "Invalid Email";
break;
case AuthError.TooManyRequests:
output = "Too Many Requests";
break;
}
AuthUIManager.instance.AwaitVerification(false, user.Email, output);
}
else
{
AuthUIManager.instance.AwaitVerification(true, user.Email, null);
Debug.Log("Email Sent Successfully");
}
}
}
public void UpdateProfilePicture(string _newPfpURL)
{
StartCoroutine(UpdateProfilePictureLogic(_newPfpURL));
}
private IEnumerator UpdateProfilePictureLogic(string _newPfpURL)
{
if (user != null)
{
UserProfile profile = new UserProfile();
try
{
UserProfile _profile = new UserProfile
{
PhotoUrl = new System.Uri(_newPfpURL),
};
profile = _profile;
}
catch
{
// LobbyManager.instance.Output("Error Fetching Image, Make Sure Your Link Is Valid!");
yield break;
}
var pfpTask = user.UpdateProfileAsync(profile);
yield return new WaitUntil(predicate: () => pfpTask.IsCompleted);
if (pfpTask.Exception != null)
{
Debug.LogError($"Updating Profile Picture was unsuccessful: {pfpTask.Exception}");
}
else
{
LobbyManager.instance.ChangePfpSuccess();
Debug.Log("Profile Image Updated Successfully");
}
}
}
}
Here is my AuthUIManager script:
using TMPro;
using UnityEngine;
public class AuthUIManager : MonoBehaviour
{
public static AuthUIManager instance;
[Header("References")]
[SerializeField]
private GameObject checkingForAccountUI;
[SerializeField]
private GameObject loginUI;
[SerializeField]
private GameObject registerUI;
[SerializeField]
private GameObject verifyEmailUI;
[SerializeField]
private TMP_Text verifyEmailText;
private void Awake()
{
if (instance == null)
{
instance = this;
}
else if (instance != this)
{
Destroy(gameObject);
}
}
private void ClearUI()
{
loginUI.SetActive(false);
registerUI.SetActive(false);
verifyEmailUI.SetActive(false);
FirebaseManager.instance.ClearOutputs();
checkingForAccountUI.SetActive(false);
}
public void LoginScreen()
{
ClearUI();
loginUI.SetActive(true);
}
public void RegisterScreen()
{
ClearUI();
registerUI.SetActive(true);
}
public void AwaitVerification(bool _emailSent, string _email, string _output)
{
ClearUI();
verifyEmailUI.SetActive(true);
if (_emailSent)
{
verifyEmailText.text = $"Sent Email!\nPleaseVerify {_email}";
}
else
{
verifyEmailText.text = $"Email Not Sent: {_output}\nPlease Verify {_email}";
}
}
}
In your FirebaseManager script you've put a semicolon ; at the end of line 264 instead of a comma ,.
Additionally you've put a desperate closed curly bracket } at the end of the file, which is not necessary.
All other errors basically originate from these two problems.
I'm trying to develop a warning if I try to connect to a specific SSID and some waiting time has passed. I've tried with a Timer class but there is some issues with Task and Threads I can't resolve.
This is my Wifi class in Xamarin.Droid
public class Wifi : Iwifi
{
private Context context;
private static WifiManager _manager;
private MyReceiver _receiver;
public void Initialize()
{
context = Android.App.Application.Context;
_manager = (WifiManager)context.GetSystemService(Context.WifiService);
_receiver = new MyReceiver();
}
public void Register()
{
IntentFilter intents = new IntentFilter();
intents.AddAction(WifiManager.ScanResultAction);
intents.AddAction(WifiManager.NetworkStateChangedAction);
context.RegisterReceiver(_receiver, intents);
}
public void Unregister()
{
context.UnregisterReceiver(_receiver);
}
public void ScanWirelessDevices()
{
_manager.StartScan();
}
public string GetConnectionSSID()
{
return _manager.ConnectionInfo.SSID;
}
public void ConnectToSSID(string SSID, string pwd)
{
if (!_manager.IsWifiEnabled)
{
_manager.SetWifiEnabled(true);
}
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.Ssid = '"' + SSID + '"';
if (pwd.Empty)
{
wifiConfiguration.AllowedKeyManagement.Set((int)KeyManagementType.None);
}
else
{
//Configuration for protected Network
}
var addNet = _manager.AddNetwork(wifiConfiguration);
if (addNet == -1)
{
_manager.Disconnect();
_manager.EnableNetwork(addNet, true);
_manager.Reconnect();
return;
}
var list = _manager.ConfiguredNetworks;
foreach (WifiConfiguration conf in list)
{
if (conf.Ssid.Equals('"' + SSID + '"'))
{
_manager.Disconnect();
_manager.EnableNetwork(conf.NetworkId, true);
_manager.Reconnect();
return;
}
}
}
public class MyReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action.Equals(WifiManager.ScanResultAvailableAction))
{
IList<ScanResult> scanResult = _manager.ScanResult;
App.Networks.NetworksList.Clear();
foreach (ScanResult result in scanResult)
{
App.Networks.NetworksList.Add(result.Ssid);
}
}
}
}
}
Then this is a part of App class in Xamarin.Forms
public partial class App: Application
{
private static ...
.
.
.
private static string _selectedSSID;
private static MainDetail _pageDetail;
public static IWifi WifiManager { get; } = DependencyService.Get<Iwifi>();
public static string SelectedSSID { get { return _selectedSSID; } set { _selectedSSID = value; } }
public static MainDetail PageDetail { get { return _pageDetail; } }
public App()
{
InitializeComponent();
WifiManager.Initialize();
WifiManager.Register();
InitViews();
MainPage = _mainPage;
Connectivity.ConnectivityChanged += NetworkEvents;
NetSearch();
}
.
.
.
public void NetSearch()
{
Task.Run(async () =>
{
while (true)
{
WifiManager.ScanWirelessDevices();
await Task.Delay(Utility.SCAN_WIFI_TIMER); //waiting 31000 milliseconds because of Scanning throttling
}
});
}
public void NetworkEvents(object sender, ConnectivityChangedEventArgs e)
{
MainMaster master = (MainMaster)_mainPage.Master;
if (e.NetworkAccess == NetworkAccess.Unknown)
{
Debug.WriteLine("Network Access Unknown " + e.ToString());
}
if (e.NetworkAccess == NetworkAccess.None)
{
Debug.WriteLine("Network Access None " + e.ToString());
}
if (e.NetworkAccess == NetworkAccess.Local)
{
Debug.WriteLine("Network Access Local " + e.ToString());
}
if (e.NetworkAccess == NetworkAccess.Internet)
{
if(selectedSSID == Wifimanager.GetConnectionInfo())
{
//WE CONNECTED!!
//Now I want to stop the Timeout Timer to attempt
}
}
if (e.NetworkAccess == NetworkAccess.ConstrainedInternet)
{
Debug.WriteLine("Network Access Constrainde Internet " + e.ToString());
}
}
}
And part of Detail page class in which I start the event of connection and where I want to start also the timeout timer
public partial class MainDetail : ContentPage
{
.
.
.
public void OnItemListClicked(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
{
return;
}
ImageCell item = (ImageCell)e.SelectedItem;
App.SelectedSSID = item.Text;
App.WifiManager.ConnectToSSID(item.Text, "");
ActivityIndicator(true);
//Now the timer should start.
//And call PageDetail.ActivityIndicator(false) and warning the user if the timeout go to 0.
listView.SelectedItem = null;
}
}
I tried with the Timers Timer class but doesn't work.. any suggestion?
Ok I figured a solution! Instead of using Thread and Task, I used Device.StartTimer.
In the event on the DetailPage I wrote:
public void OnItemListClicked(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
{
return;
}
ImageCell item = (ImageCell)e.SelectedItem;
App.SelectedSSID = item.Text;
App.WifiManager.ConnectToSSID(item.Text, "");
ActivityIndicator(true);
Device.StartTimer(TimeSpan.FromSeconds(10), () => //Waiting 10 second then if we are not connected fire the event.
{
Device.BeginInvokeOnMainThread(() =>
{
if (App.IsLogout) //variable I use to check if I can do the logout or not
{
ActivityIndicator(false);
App.SelectedSSID = "";
//My message to users "Fail to connect"
}
});
return false;
});
listView.SelectedItem = null;
}
I am trying to create a Regular Expression system as part of my program. When I pass emailSub (which is a String version of an InputField for the user's email) into other functions within the program, the emailSub goes from the email address (e.g: emailaddress#emailprovider.com) to null (I know this because the output of a Debug.Log before being passed is the email address and Debug.Log-ing it after passing it comes back with " ". This means that when it reaches the length check (IsEmailValid) it is less than 6 characters so all email addresses are rejected as invalid.
How can I fix this problem?
Thanks.
using System.Text.RegularExpressions;
using System.Globalization;
using UnityEngine;
using UnityEngine.UI;
using System;
public class RegEx : MonoBehaviour
{
public InputField emailField;
public Button acceptSubmissionButton;
public string emailSub;
public void Start()
{
var input = gameObject.GetComponent<InputField>();
var se = new InputField.SubmitEvent();
se.AddListener(SubmitName);
input.onEndEdit = se;
}
private void SubmitName(string arg0)
{
Debug.Log(arg0);
emailSub = arg0;
Debug.Log(emailSub);
}
public void Sequencer(string emailSub)
{
Debug.Log(emailSub);
IsEmailValid(emailSub);
Main(emailSub);
}
public static bool IsEmailValid(string emailSub)
{
if (emailSub.Length <= 6)
{
Debug.Log(emailSub + "1");
return false;
}
if (string.IsNullOrWhiteSpace(emailSub))
{
Debug.Log(emailSub + "2");
return false;
}
try
{
emailSub = Regex.Replace(emailSub, #"(#)(.+)$", DomainMapper, RegexOptions.None,
TimeSpan.FromMilliseconds(200));
string DomainMapper(Match match)
{
var idnConversion = new IdnMapping();
var processDomainName = idnConversion.GetAscii(match.Groups[2].Value);
Debug.Log(emailSub + "3");
return match.Groups[1].Value + processDomainName;
}
}
catch (RegexMatchTimeoutException e)
{
return false;
}
catch (ArgumentException e)
{
return false;
}
try
{
Debug.Log(emailSub + "4");
return Regex.IsMatch(emailSub, #"^(([0-9a-z]((\.(?!\.))(?<=[0-9a-z])#))" + #"(([0-9a-z][-0-
9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$", RegexOptions.IgnoreCase,
TimeSpan.FromMilliseconds(250));
}
catch (RegexMatchTimeoutException)
{
return false;
}
}
public static void Main(string emailSub)
{
if (RegEx.IsEmailValid(emailSub))
{
Debug.Log($"Valid: {emailSub}");
Debug.Log(emailSub + "5");
}
else
{
Debug.Log($"Invalid: {emailSub}");
Debug.Log(emailSub + "6");
}
}
}
The answer below was written by the person who asked the original question, but they wrote it as a replacement of the question, not in answer.
I fixed the problem, the program takes the contents of a text field and decides whether the text is in a valid email format or not. The problem was that the functions were running before the SubmitName() had updated the contents of arg0. Here is the working code:
using System.Text.RegularExpressions;
using System.Globalization;
using UnityEngine;
using UnityEngine.UI;
using System;
public class RegEx : MonoBehaviour
{
public InputField emailField;
public Button acceptSubmissionButton;
public string emailSub;
public void Start()
{
var input = gameObject.GetComponent<InputField>();
var se = new InputField.SubmitEvent();
se.AddListener(SubmitName);
input.onEndEdit = se;
}
private void SubmitName(string arg0)
{
Debug.Log(arg0);
IsEmailValid(arg0);
ValidCheck(arg0);
}
public void Sequencer(string emailSub)
{
Debug.Log(emailSub);
IsEmailValid(emailSub);
ValidCheck(emailSub);
}
public static bool IsEmailValid(string arg0)
{
if (arg0.Length <= 6)
{
return false;
}
try
{
return Regex.IsMatch(arg0, #"^(?("")("".+?(?<!\\)""#)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])#))" + #"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-0-9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250)); // The pattern is taken from an article written by Microsoft. https://learn.microsoft.com/en-us/dotnet/standard/base-types/how-to-verify-that-strings-are-in-valid-email-format
}
catch (RegexMatchTimeoutException)
{
return false;
}
}
public static void ValidCheck(string arg0)
{
if (IsEmailValid(arg0))
{
Debug.Log($"Valid: {arg0}");
}
else
{
Debug.Log($"Invalid: {arg0}");
}
}
}
I am making a trade offer bot in C# using SteamKit2, and most of the time it is successfully connecting to steam. But some of the time it just freezes when I have it output "Connecting to Steam..." right before client.connect(); is called. It happens often enough that it needs to be fixed, but I don't know what the problem is. Here is my code (a lot was taken from a SteamKit2 tutorial):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SteamKit2;
namespace ATO
{
class OfferSender
{
string username;
string password;
SteamClient client;
CallbackManager manager;
SteamUser user;
bool isRunning = false;
public OfferSender()
{
}
public void login()
{
Console.Write("Please enter your username: ");
username = Console.ReadLine();
Console.Write("Please enter your password: ");
password = Console.ReadLine();
client = new SteamClient();
manager = new CallbackManager(client);
user = client.GetHandler<SteamUser>();
new Callback<SteamClient.ConnectedCallback>(OnConnected, manager);
new Callback<SteamUser.LoggedOnCallback>(OnLoggedOn, manager);
isRunning = true;
Console.WriteLine("\nConnecting to Steam...\n");
client.Connect();
while(isRunning)
{
manager.RunWaitCallbacks(TimeSpan.FromSeconds(1));
}
Console.ReadKey();
}
public void OnConnected(SteamClient.ConnectedCallback callback)
{
if (callback.Result != EResult.OK)
{
Console.WriteLine("Error connecting to Steam: {0}", callback.Result);
isRunning = false;
return;
}
Console.WriteLine("Connected to steam.\nLogging in {0}...\n", username);
user.LogOn(new SteamUser.LogOnDetails {
Username = username,
Password = password
});
}
public void OnLoggedOn(SteamUser.LoggedOnCallback callback)
{
if (callback.Result == EResult.AccountLogonDenied)
{
Console.WriteLine("This account is SteamGuard protected.");
return;
}
if(callback.Result != EResult.OK)
{
Console.WriteLine("Unable to log in to steam {0}\n", callback.Result);
isRunning = false;
return;
}
Console.WriteLine("successfully logged in!");
Environment.Exit(0);
}
}
}
How do I fix this?
Well, after banging my head against the keyboard I finaly spoted that Steam would be requesting an AuthCode like any other new computer or browser login.
And that's it...
The code below handles either AuthCode and TwoFactor authentications:
https://github.com/SteamRE/SteamKit/tree/master/Samples/5.SteamGuard
You need to handle some more callbacks.
Here is how do I log into steam with my bot.
SteamBot.cs
using System;
using SteamKit2;
using System.Collections.Generic;
namespace StackOverflow
{
class SteamBot
{
CallbackManager m_CallbackManager;
SteamUser m_SteamUser;
SteamClient m_SteamClient;
SteamFriends m_SteamFriends;
SteamID m_SteamID;
Dictionary<string, string> m_Config;
public bool isLoggedOn { get; private set; }
public bool isReady { get; private set; }
public SteamBot(string pUsername, string pPassword)
{
isLoggedOn = false;
isReady = false;
m_Config = new Dictionary<string, string>();
m_Config.Add("username", pUsername);
m_Config.Add("password", pPassword);
Init();
RegisterCallbacks();
Connect();
}
private void Init()
{
m_SteamClient = new SteamClient();
m_CallbackManager = new CallbackManager(m_SteamClient);
m_SteamFriends = m_SteamClient.GetHandler<SteamFriends>();
m_SteamUser = m_SteamClient.GetHandler<SteamUser>();
}
private void RegisterCallbacks()
{
m_CallbackManager.Subscribe<SteamClient.ConnectedCallback>(OnConnected);
m_CallbackManager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected);
m_CallbackManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
m_CallbackManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
m_CallbackManager.Subscribe<SteamUser.AccountInfoCallback>(OnAccountInfo);
}
public void WaitForCallbacks()
{
m_CallbackManager.RunWaitCallbacks(TimeSpan.FromSeconds(1));
}
public string GetConfigValue(string pKey)
{
return m_Config[pKey];
}
public void Connect()
{
m_SteamClient.Connect();
isReady = true;
}
void OnConnected(SteamClient.ConnectedCallback pData)
{
Console.WriteLine("Connected to Steam! Logging in '{0}'...", GetConfigValue("username"));
SteamUser.LogOnDetails details = new SteamUser.LogOnDetails
{
Username = GetConfigValue("username"),
Password = GetConfigValue("password"),
};
m_SteamUser.LogOn(details);
m_SteamID = m_SteamClient.SteamID;
}
void OnDisconnected(SteamClient.DisconnectedCallback pData)
{
m_SteamClient.Disconnect();
}
void OnLoggedOff(SteamUser.LoggedOffCallback pData)
{
isLoggedOn = false;
}
void OnLoggedOn(SteamUser.LoggedOnCallback pData)
{
if (pData.Result != EResult.OK)
{
Console.WriteLine("Unable to login to Steam: {0} / {1}", pData.Result, pData.ExtendedResult);
return;
}
Console.WriteLine("Successfully logged on!");
isLoggedOn = true;
}
void OnAccountInfo(SteamUser.AccountInfoCallback pData)
{
//Announce to all friends that we are online
m_SteamFriends.SetPersonaState(EPersonaState.Online);
}
}
}
Program.cs
namespace StackOverflow
{
class Program
{
static void Main(string[] args)
{
SteamBot bot = new SteamBot("botname", "password");
while(true)
{
if(bot.isReady)
{
bot.WaitForCallbacks();
}
}
}
}
}
You need to add Steam Directory.Initialize().Wait(); before you attempt to connect so SteamKit can update its internal list of servers, as explained here.
So, I am working on a Unity project in which I need to implement client/server functionality.
The client has its own "scene" and the server has its own scene as well. The server code and a networkView are attached to the Main Camera in their scene. The code is as follows:
using UnityEngine;
using System.Collections;
using System.Net;
using System.Collections.Generic;
public class NetworkManagerCS : MonoBehaviour {
public int loadlevel;
public int connectPort = 25000;
public string hostname;
public string GameName = "Historical Grounds";
private bool refreshing;
private HostData[] hostData;
private Dictionary<string, string> playerList = new Dictionary<string, string>();
string textToEdit = "Type text here";
// This is for debuggin purposes only!! Will be deprecated
public void OnGUI() {
if (Network.peerType == NetworkPeerType.Disconnected) {
GUILayout.Label("Connection status: Disconnected");
GUILayout.BeginVertical();
if (GUILayout.Button("Connect as client"))
{
ConnectToServer();
}
if (GUILayout.Button("Start Server"))
{
Network.InitializeServer(4, connectPort, true);
MasterServer.RegisterHost(GameName, "Tutorial Game", "This is a turn based shooter");
//Network.Instantiate(camera, transform.position, transform.rotation, 0);
}
GUILayout.EndVertical();
}
else
{
// Connecting...
if (Network.peerType == NetworkPeerType.Connecting)
{
GUILayout.Label("Connection status: Connecting");
}
// Clientside buttons
else if (Network.peerType == NetworkPeerType.Client)
{
GUILayout.Label("Connection status: Client!");
GUILayout.Label("Ping to server: " + Network.GetAveragePing(Network.connections[0]));
textToEdit = GUILayout.TextField(textToEdit, 25);
if( GUILayout.Button("Attack Server")) {
float[] args = new float[3];
args[0] = float.Parse(textToEdit);
args[1] = 4.123f;
args[2] = 23.2f;
networkView.RPC("AttackServer", RPCMode.AllBuffered, args);
}
}
// Serverside
else if (Network.peerType == NetworkPeerType.Server)
{
GUILayout.Label("Connection status: Server!");
GUILayout.Label("Hostname is:" + System.Net.Dns.GetHostName() );
GUILayout.Label("Connections: " + Network.connections.Length);
}
// Disconnect happens in both server and client
if (GUILayout.Button("Disconnect"))
{
Network.Disconnect(200);
}
}
}
// AKA While(true)
public void Update() {
/*
* If we have a "refreshing" flag, then we poll the master server
* until we get a length larger than 0. Then, we connect to server.
*/
if(refreshing) {
if (MasterServer.PollHostList().Length > 0) {
refreshing = false;
Debug.Log(MasterServer.PollHostList().Length);
hostData = MasterServer.PollHostList();
ConnectToServer();
}
}
}
/*
* If hostData does not exist, refresh
* Otherwise, connect to the first game you see.
*
* This is the "dumb" approach, but I assume that there are not going to be more
* than one game running at a time...
*/
public void ConnectToServer() {
if (hostData == null) {
MasterServer.RequestHostList(GameName);
refreshing = true;
} else {
Network.Connect(hostData[0]);
}
}
/*
* Keeping this here so that I will remember to add system info sends
*/
public void OnConnectedToServer()
{
//Application.LoadLevel(loadlevel);
}
/*
* DEBUG FUNCTION!!! This will be called when someone disconnected from
* the msater server
*/
public void OnDisconnectedFromServer(NetworkDisconnection info) {
if (info == NetworkDisconnection.LostConnection) {
if (Network.peerType == NetworkPeerType.Client) {
Debug.Log ("Client has lost connection");
} else {
Debug.Log ("Server has lost connection");
}
} else {
Debug.Log ("Disconnected Successfully");
}
}
/*
* Lawl, fail....
*/
public void OnFailedToConnect(NetworkConnectionError error)
{
Debug.LogError(error.ToString());
Network.Disconnect(400);
}
/*
* The purpose of this function is to assign a monster to a player
* Once all monsters have been assigned, I guess the Update() function will
* RPC to the phones that they are ready to play.
*/
public void OnPlayerConnected(NetworkPlayer player) {
networkView.RPC("assignPlayer", RPCMode.All, player);
}
/*
* Not interesting... Server initialized..
*/
public void OnServerInitialized()
{
//Application.LoadLevel(loadlevel);
Debug.Log("Server Started");
}
void OnMasterServerEvent(MasterServerEvent msg) {
if (msg == MasterServerEvent.RegistrationSucceeded){
Debug.Log("Registered Server!");
Network.isMessageQueueRunning = true;
}
}
/*void OnPlayerDisconnected(NetworkPlayer player) {
Transform playerTransform = GameObject.Find("Player_" + player.guid);
if (playerTransform != null) {
Destroy (playerTransform.gameObject);
}
Network.RemoveRPCs(player);
Network.DestroyPlayerObjects(player);
}*/
// Testers - Should deprecate
/*[RPC]
public void AttackServer(float[] args) {
foreach (float value in args) {
Debug.Log ("Server is under attack with force " + value);
}
}*/
// RPC's Server Side
[RPC]
public void sendLifeCount(NetworkPlayer player) {
Debug.Log("Sending Life Count to " + player.ipAddress);
}
[RPC]
public void isDead(NetworkPlayer player) {
Debug.Log("You're dead! " + player.ipAddress);
}
[RPC]
public void unlockScreen(NetworkPlayer player) {
Debug.Log("Unlocking screen for.." + player.ipAddress);
}
[RPC]
public void assignPlayer(NetworkPlayer player) {
playerList.Add(player.guid, "1");
Debug.Log(playerList[player.guid]);
Debug.Log("Player connected from: " + player.ipAddress + ":" + player.port);
Debug.Log("The player on IP " + player.ipAddress + " has been assigned the x monster");
}
public Object networkprefab { get; set; }
}
The client on the other hand, is in another scene and its code is here: (no networkView attached, due to problems...
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Text.RegularExpressions;
public center code herelass InputField : MonoBehaviour {
// Client-server bullshit
private int loadlevel;
private HostData[] hostData;
private bool refreshing;
public string GameName = "Historical Grounds";
private bool connected;
public Canvas mainCanvas;
public Canvas gameCanvas;
public Button Connect;
public Text nameFieldInput;
public Text nameField;
public Text Error;
private string userName;
void Awake()
{
if (connected)
{
mainCanvas.enabled = false;
gameCanvas.enabled = true;
}
else {
mainCanvas.enabled = true;
gameCanvas.enabled = false;
}
Debug.Log(connected);
}
public void Update()
{
/*
* If we have a "refreshing" flag, then we poll the master server
* until we get a length larger than 0. Then, we connect to server.
*/
if (refreshing)
{
if (MasterServer.PollHostList().Length > 0)
{
refreshing = false;
Debug.Log(MasterServer.PollHostList().Length);
hostData = MasterServer.PollHostList();
ConnectToServer();
}
}
}
public void onConnect()
{
ConnectToServer();
}
public void OnConnectedToServer()
{
var viewID = Network.AllocateViewID();
}
public void ConnectToServer()
{
if (hostData == null)
{
MasterServer.RequestHostList(GameName);
refreshing = true;
}
else
{
if (Switch())
{
connected = true;
Network.Connect(hostData[0]);
}
}
}
private bool Switch(){
userName = nameFieldInput.text;
Debug.Log(userName);
if(Validate(userName)){
nameField.text = userName;
mainCanvas.enabled = false;
gameCanvas.enabled = true;
connected = true;
return true;
} else {
Error.text = "Invalid name!" + "\n" + "Name should be 2-8 characters and start with a capital letter";
return false;
}
}
private bool Validate(string input){
string pattern = #"^[A-Z][A-Za-z0-9][A-Za-z0-9]+";
Match match = Regex.Match(input, pattern);
if (match.Success)
{
return true;
}
return false;
}
public void OnDisconnectedFromServer(NetworkDisconnection info)
{
if (info == NetworkDisconnection.LostConnection)
{
if (Network.peerType == NetworkPeerType.Client)
{
Debug.Log("Client has lost connection");
}
else
{
Debug.Log("Server has lost connection");
}
}
else
{
Debug.Log("Disconnected Successfully");
}
}
public void OnFailedToConnect(NetworkConnectionError error)
{
Debug.LogError(error.ToString());
Debug.Log("FAIL!");
}
public void OnDisconnectedFromServer()
{
connected = false;
Debug.Log("Lawl Disconnected");
}
}
TL;DR: I keep getting that error message when trying to invoke an RPC ( fire() ) from the client to the server. Anyone know why?
Thanks!!