XP done
This commit is contained in:
@@ -101849,6 +101849,8 @@ MonoBehaviour:
|
||||
gemsTxt: {fileID: 809069760}
|
||||
metalTxt: {fileID: 1225876156}
|
||||
oxygenTxt: {fileID: 1428544882}
|
||||
levelTxt: {fileID: 1882249801}
|
||||
levelSlider: {fileID: 1941152343}
|
||||
--- !u!4 &981460998
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -183641,9 +183643,9 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 142.74982, y: 0.27972412}
|
||||
m_SizeDelta: {x: 7.143589, y: -117}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 139.17798, y: 0.27972412}
|
||||
m_SizeDelta: {x: 14.659, y: -117}
|
||||
m_Pivot: {x: 0, y: 0.5}
|
||||
--- !u!114 &1812220813
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -196982,7 +196984,7 @@ MonoBehaviour:
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_DisabledColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
@@ -196996,7 +196998,7 @@ MonoBehaviour:
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_Interactable: 0
|
||||
m_TargetGraphic: {fileID: 1941152344}
|
||||
m_FillRect: {fileID: 1812220812}
|
||||
m_HandleRect: {fileID: 0}
|
||||
@@ -197004,7 +197006,7 @@ MonoBehaviour:
|
||||
m_MinValue: 0
|
||||
m_MaxValue: 1
|
||||
m_WholeNumbers: 0
|
||||
m_Value: 0.132
|
||||
m_Value: 1
|
||||
m_OnValueChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
@@ -197022,7 +197024,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.93333334, g: 0.9372549, b: 0.94509804, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastTarget: 0
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
@@ -213304,6 +213306,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 0780243d2e94ca4c88eafaf9c28ed56e, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
buildingId:
|
||||
productionRate: 0
|
||||
collectableAmount: 0
|
||||
btn: {fileID: 2098386628}
|
||||
|
||||
@@ -23,6 +23,7 @@ MonoBehaviour:
|
||||
- name: Energy
|
||||
value: 50
|
||||
price: 10000
|
||||
xpGain: 50
|
||||
- level: 2
|
||||
stats:
|
||||
- name: Stat 1
|
||||
@@ -32,4 +33,8 @@ MonoBehaviour:
|
||||
- name: Energy
|
||||
value: 500
|
||||
price: 15000
|
||||
xpGain: 175
|
||||
description: This is the Hall (Main Hall)
|
||||
collectable: 0
|
||||
resourceType: 0
|
||||
productinoRates: []
|
||||
|
||||
@@ -19,6 +19,8 @@ MonoBehaviour:
|
||||
- name: Production rate
|
||||
value: 10%
|
||||
price: 8500
|
||||
xpGain: 50
|
||||
description: This is a Rocket Repair
|
||||
collectable: 0
|
||||
resourceType: 0
|
||||
productinoRates: []
|
||||
|
||||
@@ -23,6 +23,7 @@ MonoBehaviour:
|
||||
- name: Something else
|
||||
value: 40 %
|
||||
price: 12500
|
||||
xpGain: 150
|
||||
- level: 2
|
||||
stats:
|
||||
- name: Power
|
||||
@@ -32,4 +33,8 @@ MonoBehaviour:
|
||||
- name: Something else
|
||||
value: 80 %
|
||||
price: 22500
|
||||
xpGain: 280
|
||||
description: This is a Research Lab
|
||||
collectable: 0
|
||||
resourceType: 0
|
||||
productinoRates: []
|
||||
|
||||
@@ -61,6 +61,7 @@ public class Building : MonoBehaviour
|
||||
Mathf.Clamp(curLevel++,0, buildingData.levels.Count-1);
|
||||
|
||||
DBmanager.UpgradeBuilding(buildingData.buildingName, curLevel);
|
||||
DBmanager.SetXp(DBmanager.Xp + buildingData.levels[curLevel].xpGain);
|
||||
}
|
||||
//
|
||||
// public List<Collider> buildingsInsideMe = new List<Collider>();
|
||||
@@ -104,10 +105,10 @@ public class BuildingState{
|
||||
public Vector3 position;
|
||||
public DateTime lastCollectedTimestamp;
|
||||
|
||||
public BuildingState(string m_id, int m_level, Vector3 m_position){
|
||||
public BuildingState(string m_id, int m_level, Vector3 m_position, DateTime _lastCollectedTimestamp){
|
||||
id = m_id;
|
||||
level = m_level;
|
||||
position = m_position;
|
||||
lastCollectedTimestamp = DBmanager.GetNetworkTime();
|
||||
lastCollectedTimestamp= _lastCollectedTimestamp;
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@ public class BuildingLevel{
|
||||
public int level = 0;
|
||||
public List<BuildingStat> stats;
|
||||
public int price = 1000;
|
||||
public int xpGain = 100;
|
||||
|
||||
public BuildingLevel(int _level, List<BuildingStat> _stats, int _price){
|
||||
level = _level;
|
||||
|
||||
@@ -13,6 +13,9 @@ public class DBmanager : MonoBehaviour
|
||||
public static string phpRoot = "http://38.242.232.13/upf/";
|
||||
|
||||
public static string username = null;
|
||||
|
||||
private static float level = 0;
|
||||
private static int xp = 0;
|
||||
private static int coins = 0;
|
||||
private static int gems = 0;
|
||||
private static int metal = 0;
|
||||
@@ -20,10 +23,12 @@ public class DBmanager : MonoBehaviour
|
||||
public static List<BuildingState> buildingStates = new List<BuildingState>();
|
||||
public static UnityEvent OnStateChanged = new UnityEvent();
|
||||
|
||||
public static int Xp => xp;
|
||||
public static int Coins => coins;
|
||||
public static int Gems => gems;
|
||||
public static int Metal => metal;
|
||||
public static int Oxygen => oxygen;
|
||||
public static float Level => level;
|
||||
|
||||
|
||||
public static bool LoggedIn { get { return username != null; } }
|
||||
@@ -49,7 +54,7 @@ public class DBmanager : MonoBehaviour
|
||||
var ipEndPoint = new IPEndPoint(addresses[0], 123);
|
||||
//NTP uses UDP
|
||||
|
||||
using(var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
|
||||
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
|
||||
{
|
||||
socket.Connect(ipEndPoint);
|
||||
|
||||
@@ -86,140 +91,215 @@ public class DBmanager : MonoBehaviour
|
||||
|
||||
static uint SwapEndianness(ulong x)
|
||||
{
|
||||
return (uint) (((x & 0x000000ff) << 24) +
|
||||
return (uint)(((x & 0x000000ff) << 24) +
|
||||
((x & 0x0000ff00) << 8) +
|
||||
((x & 0x00ff0000) >> 8) +
|
||||
((x & 0xff000000) >> 24));
|
||||
}
|
||||
|
||||
public async static Task SetXp(int newValue, bool justOffline = false)
|
||||
{
|
||||
WWWForm form = new WWWForm();
|
||||
form.AddField("name", username);
|
||||
form.AddField("xp", newValue);
|
||||
if (justOffline) { xp = newValue; }
|
||||
else
|
||||
{
|
||||
using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_xp.php", form))
|
||||
{
|
||||
var operation = www.SendWebRequest();
|
||||
while (!operation.isDone)
|
||||
{
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
public async static Task SetCoins(int newValue, bool justOffline = false){
|
||||
if (www.downloadHandler.text == "0")
|
||||
{
|
||||
xp = newValue;
|
||||
// Debug
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Response : " + www.downloadHandler.text);
|
||||
Debug.LogWarning("Failed to set xp to " + newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for(int i =0; i < xp / 100; i++){
|
||||
// i
|
||||
// }
|
||||
|
||||
level = 1 + (Mathf.Sqrt((float)xp / 100f));
|
||||
Debug.Log("Level : " + (float)xp / 100f + " : " + level);
|
||||
GameManagerInstance.gameManager.RefreshData();
|
||||
OnStateChanged.Invoke();
|
||||
}
|
||||
|
||||
public async static Task SetCoins(int newValue, bool justOffline = false)
|
||||
{
|
||||
WWWForm form = new WWWForm();
|
||||
form.AddField("name", username);
|
||||
form.AddField("coins", newValue);
|
||||
if(justOffline){coins=newValue; return;}
|
||||
using(UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_coins.php",form)){
|
||||
if (justOffline) { coins = newValue; return; }
|
||||
using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_coins.php", form))
|
||||
{
|
||||
var operation = www.SendWebRequest();
|
||||
while(!operation.isDone){
|
||||
while (!operation.isDone)
|
||||
{
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
if(www.downloadHandler.text=="0"){
|
||||
if (www.downloadHandler.text == "0")
|
||||
{
|
||||
coins = newValue;
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Response : " + www.downloadHandler.text);
|
||||
Debug.LogWarning("Failed to set coins to " + newValue);
|
||||
}
|
||||
}
|
||||
|
||||
GameManagerInstance.gameManager.RefreshData();
|
||||
OnStateChanged.Invoke();
|
||||
}
|
||||
|
||||
public async static void SetGems(int newValue,bool justOffline=false){
|
||||
public async static void SetGems(int newValue, bool justOffline = false)
|
||||
{
|
||||
WWWForm form = new WWWForm();
|
||||
form.AddField("name", username);
|
||||
form.AddField("gems", newValue);
|
||||
if(justOffline){gems=newValue; return;}
|
||||
using(UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_gems.php",form)){
|
||||
if (justOffline) { gems = newValue; return; }
|
||||
using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_gems.php", form))
|
||||
{
|
||||
var operation = www.SendWebRequest();
|
||||
while(!operation.isDone){
|
||||
while (!operation.isDone)
|
||||
{
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
if(www.downloadHandler.text=="0"){
|
||||
if (www.downloadHandler.text == "0")
|
||||
{
|
||||
gems = newValue;
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Response : " + www.downloadHandler.text);
|
||||
Debug.LogWarning("Failed to set gems to " + newValue);
|
||||
}
|
||||
}
|
||||
|
||||
GameManagerInstance.gameManager.RefreshData();
|
||||
OnStateChanged.Invoke();
|
||||
}
|
||||
|
||||
public async static void SetMetal(int newValue,bool justOffline=false){
|
||||
public async static void SetMetal(int newValue, bool justOffline = false)
|
||||
{
|
||||
WWWForm form = new WWWForm();
|
||||
form.AddField("name", username);
|
||||
form.AddField("metal", newValue);
|
||||
if(justOffline){metal=newValue; return;}
|
||||
using(UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_metal.php",form)){
|
||||
if (justOffline) { metal = newValue; return; }
|
||||
using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_metal.php", form))
|
||||
{
|
||||
var operation = www.SendWebRequest();
|
||||
while(!operation.isDone){
|
||||
while (!operation.isDone)
|
||||
{
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
if(www.downloadHandler.text=="0"){
|
||||
if (www.downloadHandler.text == "0")
|
||||
{
|
||||
metal = newValue;
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Response : " + www.downloadHandler.text);
|
||||
Debug.LogWarning("Failed to set metal to " + newValue);
|
||||
}
|
||||
}
|
||||
|
||||
GameManagerInstance.gameManager.RefreshData();
|
||||
OnStateChanged.Invoke();
|
||||
}
|
||||
|
||||
public async static void SetOxygen(int newValue,bool justOffline=false){
|
||||
public async static void SetOxygen(int newValue, bool justOffline = false)
|
||||
{
|
||||
WWWForm form = new WWWForm();
|
||||
form.AddField("name", username);
|
||||
form.AddField("oxygen", newValue);
|
||||
if(justOffline){oxygen=newValue; return;}
|
||||
using(UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_oxygen.php",form)){
|
||||
if (justOffline) { oxygen = newValue; return; }
|
||||
using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_oxygen.php", form))
|
||||
{
|
||||
var operation = www.SendWebRequest();
|
||||
while(!operation.isDone){
|
||||
while (!operation.isDone)
|
||||
{
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
if(www.downloadHandler.text=="0"){
|
||||
if (www.downloadHandler.text == "0")
|
||||
{
|
||||
oxygen = newValue;
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Response : " + www.downloadHandler.text);
|
||||
Debug.LogWarning("Failed to set oxygen to " + newValue);
|
||||
}
|
||||
}
|
||||
|
||||
GameManagerInstance.gameManager.RefreshData();
|
||||
OnStateChanged.Invoke();
|
||||
}
|
||||
|
||||
public static bool GetBuildingStates(string rawData){
|
||||
public static bool GetBuildingStates(string rawData)
|
||||
{
|
||||
bool success = false;
|
||||
try{
|
||||
//try{
|
||||
|
||||
buildingStates = JsonConvert.DeserializeObject<List<BuildingState>>(rawData);
|
||||
Debug.Log("Updating buildings data, isNull: " + (buildingStates==null).ToString());
|
||||
if(buildingStates==null){
|
||||
buildingStates = new List<BuildingState>();
|
||||
}
|
||||
success=true;
|
||||
}catch(Exception e){
|
||||
Debug.LogError(e.Message);
|
||||
Debug.LogError("Error updating buildings from server, Response:" + rawData);
|
||||
success=false;
|
||||
buildingStates = JsonConvert.DeserializeObject<List<BuildingState>>(rawData);
|
||||
Debug.Log("Updating buildings data, isNull: " + (buildingStates == null).ToString());
|
||||
if (buildingStates == null)
|
||||
{
|
||||
buildingStates = new List<BuildingState>();
|
||||
}
|
||||
success = true;
|
||||
// }catch(Exception e){
|
||||
// Debug.LogError(e.Message+'\n' + e.StackTrace);
|
||||
//
|
||||
// Debug.LogError("Error updating buildings from server, Response:" + rawData);
|
||||
// success=false;
|
||||
// }
|
||||
|
||||
OnStateChanged.Invoke();
|
||||
return success;
|
||||
}
|
||||
|
||||
public async static Task AddBuilding(BuildingData buildingData){
|
||||
public async static Task AddBuilding(BuildingData buildingData)
|
||||
{
|
||||
|
||||
foreach (BuildingState buildingState in buildingStates){
|
||||
if(buildingState.id == buildingData.buildingName){
|
||||
foreach (BuildingState buildingState in buildingStates)
|
||||
{
|
||||
if (buildingState.id == buildingData.buildingName)
|
||||
{
|
||||
Debug.LogError("Building already exists. Cannot add " + buildingState.id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
buildingStates.Add(new BuildingState(buildingData.buildingName, 0,Vector3.zero));
|
||||
Debug.Log("Added new building "+ buildingData.buildingName);
|
||||
Debug.Log("adding new building " + buildingData.buildingName);
|
||||
buildingStates.Add(new BuildingState(buildingData.buildingName, 0, Vector3.zero, GetNetworkTime()));
|
||||
Debug.Log("Added new building " + buildingData.buildingName);
|
||||
await UpdateBuildingsToServer();
|
||||
|
||||
OnStateChanged.Invoke();
|
||||
SetXp(xp + buildingData.levels[0].xpGain);
|
||||
}
|
||||
|
||||
public async static Task UpgradeBuilding(string id, int newLevel){
|
||||
for(int i=0; i < buildingStates.Count; i++){
|
||||
if(buildingStates[i].id == id){
|
||||
public async static Task UpgradeBuilding(string id, int newLevel)
|
||||
{
|
||||
for (int i = 0; i < buildingStates.Count; i++)
|
||||
{
|
||||
if (buildingStates[i].id == id)
|
||||
{
|
||||
buildingStates[i].level = newLevel;
|
||||
Debug.Log("Upgrading " + id + " to " + newLevel);
|
||||
break;
|
||||
@@ -232,9 +312,12 @@ public class DBmanager : MonoBehaviour
|
||||
}
|
||||
|
||||
|
||||
public async static Task CollectBuilding(string id){
|
||||
for(int i=0; i < buildingStates.Count; i++){
|
||||
if(buildingStates[i].id == id){
|
||||
public async static Task CollectBuilding(string id)
|
||||
{
|
||||
for (int i = 0; i < buildingStates.Count; i++)
|
||||
{
|
||||
if (buildingStates[i].id == id)
|
||||
{
|
||||
buildingStates[i].lastCollectedTimestamp = GetNetworkTime();
|
||||
Debug.Log("Setting " + id + " last collected to " + buildingStates[i].lastCollectedTimestamp);
|
||||
break;
|
||||
@@ -246,9 +329,12 @@ public class DBmanager : MonoBehaviour
|
||||
OnStateChanged.Invoke();
|
||||
}
|
||||
|
||||
public async static Task RelocateBuilding(string id, Vector3 newPosition){
|
||||
for(int i=0; i < buildingStates.Count; i++){
|
||||
if(buildingStates[i].id == id){
|
||||
public async static Task RelocateBuilding(string id, Vector3 newPosition)
|
||||
{
|
||||
for (int i = 0; i < buildingStates.Count; i++)
|
||||
{
|
||||
if (buildingStates[i].id == id)
|
||||
{
|
||||
buildingStates[i].position = newPosition;
|
||||
Debug.Log("Relocating " + id + " to " + newPosition);
|
||||
// break;
|
||||
@@ -260,7 +346,8 @@ public class DBmanager : MonoBehaviour
|
||||
OnStateChanged.Invoke();
|
||||
}
|
||||
|
||||
public async static Task UpdateBuildingsToServer(){
|
||||
public async static Task UpdateBuildingsToServer()
|
||||
{
|
||||
string buildingsJson = JsonConvert.SerializeObject(buildingStates);
|
||||
Debug.Log(buildingsJson);
|
||||
|
||||
@@ -268,15 +355,20 @@ public class DBmanager : MonoBehaviour
|
||||
form.AddField("name", username);
|
||||
form.AddField("buildings", buildingsJson);
|
||||
|
||||
using(UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_buildings.php",form)){
|
||||
using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_buildings.php", form))
|
||||
{
|
||||
var operation = www.SendWebRequest();
|
||||
while(!operation.isDone){
|
||||
while (!operation.isDone)
|
||||
{
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
if(www.downloadHandler.text=="0"){
|
||||
if (www.downloadHandler.text == "0")
|
||||
{
|
||||
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Response : " + www.downloadHandler.text);
|
||||
Debug.LogWarning("Failed to set buildings to " + buildingsJson);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using UnityEngine;
|
||||
using TMPro;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class GameManager : MonoBehaviour
|
||||
{
|
||||
@@ -12,7 +13,8 @@ public class GameManager : MonoBehaviour
|
||||
public TMP_Text gemsTxt;
|
||||
public TMP_Text metalTxt;
|
||||
public TMP_Text oxygenTxt;
|
||||
|
||||
public TMP_Text levelTxt;
|
||||
public Slider levelSlider;
|
||||
void Start()
|
||||
{
|
||||
GameManagerInstance.gameManager = this;
|
||||
@@ -39,6 +41,10 @@ public class GameManager : MonoBehaviour
|
||||
gemsTxt.text = DBmanager.Gems.ToString();
|
||||
metalTxt.text = DBmanager.Metal.ToString();
|
||||
oxygenTxt.text = DBmanager.Oxygen.ToString();
|
||||
levelTxt.text = Mathf.CeilToInt(DBmanager.Level).ToString();
|
||||
|
||||
float levelExcess = DBmanager.Level - Mathf.FloorToInt(DBmanager.Level);
|
||||
levelSlider.value = levelExcess;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,12 +86,15 @@ public class LoginManager : MonoBehaviour
|
||||
PlayerPrefs.SetString("password", login_password.text);
|
||||
PlayerPrefs.Save();}
|
||||
DBmanager.username = login_username.text;
|
||||
DBmanager.SetXp(int.Parse(www.text.Split('\t')[6]),true);
|
||||
DBmanager.GetBuildingStates(www.text.Split('\t')[5]);
|
||||
DBmanager.SetOxygen(int.Parse(www.text.Split('\t')[4]),true);
|
||||
DBmanager.SetMetal(int.Parse(www.text.Split('\t')[3]),true);
|
||||
DBmanager.SetGems(int.Parse(www.text.Split('\t')[2]),true);
|
||||
DBmanager.SetCoins(int.Parse(www.text.Split('\t')[1]),true);
|
||||
|
||||
Debug.Log("XP : " + DBmanager.Xp);
|
||||
|
||||
UnityEngine.SceneManagement.SceneManager.LoadScene(1);
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user