新增Debug辅助Insist
This commit is contained in:
17
source/bin/framework.d.ts
vendored
17
source/bin/framework.d.ts
vendored
@@ -93,12 +93,27 @@ declare module es {
|
|||||||
protected update(currentTime?: number): Promise<void>;
|
protected update(currentTime?: number): Promise<void>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
declare module es {
|
||||||
|
enum LogType {
|
||||||
|
error = 0,
|
||||||
|
warn = 1,
|
||||||
|
log = 2,
|
||||||
|
info = 3,
|
||||||
|
trace = 4
|
||||||
|
}
|
||||||
|
class Debug {
|
||||||
|
static warnIf(condition: boolean, format: string, ...args: any[]): void;
|
||||||
|
static warn(format: string, ...args: any[]): void;
|
||||||
|
static error(format: string, ...args: any[]): void;
|
||||||
|
static log(type: LogType, format: string, ...args: any[]): void;
|
||||||
|
}
|
||||||
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
/**
|
/**
|
||||||
* 我们在这里存储了各种系统的默认颜色,如对撞机调试渲染、Debug.drawText等。
|
* 我们在这里存储了各种系统的默认颜色,如对撞机调试渲染、Debug.drawText等。
|
||||||
* 命名方式尽可能采用CLASS-THING,以明确它的使用位置
|
* 命名方式尽可能采用CLASS-THING,以明确它的使用位置
|
||||||
*/
|
*/
|
||||||
class Debug {
|
class DebugDefault {
|
||||||
static debugText: number;
|
static debugText: number;
|
||||||
static colliderBounds: number;
|
static colliderBounds: number;
|
||||||
static colliderEdge: number;
|
static colliderEdge: number;
|
||||||
|
|||||||
@@ -126,10 +126,7 @@ var es;
|
|||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
set: function (value) {
|
set: function (value) {
|
||||||
if (!value) {
|
es.Insist.isNotNull(value, "场景不能为空");
|
||||||
console.error("场景不能为空");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this._instance._scene == null) {
|
if (this._instance._scene == null) {
|
||||||
this._instance._scene = value;
|
this._instance._scene = value;
|
||||||
this._instance.onSceneChanged();
|
this._instance.onSceneChanged();
|
||||||
@@ -249,26 +246,90 @@ var es;
|
|||||||
es.Core = Core;
|
es.Core = Core;
|
||||||
})(es || (es = {}));
|
})(es || (es = {}));
|
||||||
var es;
|
var es;
|
||||||
|
(function (es) {
|
||||||
|
var LogType;
|
||||||
|
(function (LogType) {
|
||||||
|
LogType[LogType["error"] = 0] = "error";
|
||||||
|
LogType[LogType["warn"] = 1] = "warn";
|
||||||
|
LogType[LogType["log"] = 2] = "log";
|
||||||
|
LogType[LogType["info"] = 3] = "info";
|
||||||
|
LogType[LogType["trace"] = 4] = "trace";
|
||||||
|
})(LogType = es.LogType || (es.LogType = {}));
|
||||||
|
var Debug = /** @class */ (function () {
|
||||||
|
function Debug() {
|
||||||
|
}
|
||||||
|
Debug.warnIf = function (condition, format) {
|
||||||
|
var args = [];
|
||||||
|
for (var _i = 2; _i < arguments.length; _i++) {
|
||||||
|
args[_i - 2] = arguments[_i];
|
||||||
|
}
|
||||||
|
if (condition)
|
||||||
|
this.log(LogType.warn, format, args);
|
||||||
|
};
|
||||||
|
Debug.warn = function (format) {
|
||||||
|
var args = [];
|
||||||
|
for (var _i = 1; _i < arguments.length; _i++) {
|
||||||
|
args[_i - 1] = arguments[_i];
|
||||||
|
}
|
||||||
|
this.log(LogType.warn, format, args);
|
||||||
|
};
|
||||||
|
Debug.error = function (format) {
|
||||||
|
var args = [];
|
||||||
|
for (var _i = 1; _i < arguments.length; _i++) {
|
||||||
|
args[_i - 1] = arguments[_i];
|
||||||
|
}
|
||||||
|
this.log(LogType.error, format, args);
|
||||||
|
};
|
||||||
|
Debug.log = function (type, format) {
|
||||||
|
var args = [];
|
||||||
|
for (var _i = 2; _i < arguments.length; _i++) {
|
||||||
|
args[_i - 2] = arguments[_i];
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case LogType.error:
|
||||||
|
console.error(type + ": " + StringUtils.format(format, args));
|
||||||
|
break;
|
||||||
|
case LogType.warn:
|
||||||
|
console.warn(type + ": " + StringUtils.format(format, args));
|
||||||
|
break;
|
||||||
|
case LogType.log:
|
||||||
|
console.log(type + ": " + StringUtils.format(format, args));
|
||||||
|
break;
|
||||||
|
case LogType.info:
|
||||||
|
console.info(type + ": " + StringUtils.format(format, args));
|
||||||
|
break;
|
||||||
|
case LogType.trace:
|
||||||
|
console.trace(type + ": " + StringUtils.format(format, args));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('argument out of range');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Debug;
|
||||||
|
}());
|
||||||
|
es.Debug = Debug;
|
||||||
|
})(es || (es = {}));
|
||||||
|
var es;
|
||||||
(function (es) {
|
(function (es) {
|
||||||
/**
|
/**
|
||||||
* 我们在这里存储了各种系统的默认颜色,如对撞机调试渲染、Debug.drawText等。
|
* 我们在这里存储了各种系统的默认颜色,如对撞机调试渲染、Debug.drawText等。
|
||||||
* 命名方式尽可能采用CLASS-THING,以明确它的使用位置
|
* 命名方式尽可能采用CLASS-THING,以明确它的使用位置
|
||||||
*/
|
*/
|
||||||
var Debug = /** @class */ (function () {
|
var DebugDefault = /** @class */ (function () {
|
||||||
function Debug() {
|
function DebugDefault() {
|
||||||
}
|
}
|
||||||
Debug.debugText = 0xffffff;
|
DebugDefault.debugText = 0xffffff;
|
||||||
Debug.colliderBounds = 0xffffff * 0.3;
|
DebugDefault.colliderBounds = 0xffffff * 0.3;
|
||||||
Debug.colliderEdge = 0x8B0000;
|
DebugDefault.colliderEdge = 0x8B0000;
|
||||||
Debug.colliderPosition = 0xFFFF00;
|
DebugDefault.colliderPosition = 0xFFFF00;
|
||||||
Debug.colliderCenter = 0xFF0000;
|
DebugDefault.colliderCenter = 0xFF0000;
|
||||||
Debug.renderableBounds = 0xFFFF00;
|
DebugDefault.renderableBounds = 0xFFFF00;
|
||||||
Debug.renderableCenter = 0x9932CC;
|
DebugDefault.renderableCenter = 0x9932CC;
|
||||||
Debug.verletParticle = 0xDC345E;
|
DebugDefault.verletParticle = 0xDC345E;
|
||||||
Debug.verletConstraintEdge = 0x433E36;
|
DebugDefault.verletConstraintEdge = 0x433E36;
|
||||||
return Debug;
|
return DebugDefault;
|
||||||
}());
|
}());
|
||||||
es.Debug = Debug;
|
es.DebugDefault = DebugDefault;
|
||||||
})(es || (es = {}));
|
})(es || (es = {}));
|
||||||
var es;
|
var es;
|
||||||
(function (es) {
|
(function (es) {
|
||||||
@@ -1312,11 +1373,9 @@ var es;
|
|||||||
* @param component
|
* @param component
|
||||||
*/
|
*/
|
||||||
Scene.prototype.removeSceneComponent = function (component) {
|
Scene.prototype.removeSceneComponent = function (component) {
|
||||||
if (!new linq.List(this._sceneComponents).contains(component)) {
|
var sceneComponentList = new linq.List(this._sceneComponents);
|
||||||
console.warn("SceneComponent" + component + "\u4E0D\u5728SceneComponents\u5217\u8868\u4E2D!");
|
es.Insist.isTrue(sceneComponentList.contains(component), "SceneComponent" + component + "\u4E0D\u5728SceneComponents\u5217\u8868\u4E2D!");
|
||||||
return;
|
sceneComponentList.remove(component);
|
||||||
}
|
|
||||||
new linq.List(this._sceneComponents).remove(component);
|
|
||||||
component.onRemovedFromScene();
|
component.onRemovedFromScene();
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
@@ -2141,9 +2200,7 @@ var es;
|
|||||||
};
|
};
|
||||||
ArcadeRigidbody.prototype.onAddedToEntity = function () {
|
ArcadeRigidbody.prototype.onAddedToEntity = function () {
|
||||||
this._collider = this.entity.getComponent(es.Collider);
|
this._collider = this.entity.getComponent(es.Collider);
|
||||||
if (this._collider == null) {
|
es.Debug.warnIf(this._collider == null, "ArcadeRigidbody 没有 Collider。ArcadeRigidbody需要一个Collider!");
|
||||||
console.warn("ArcadeRigidbody 没有 Collider。ArcadeRigidbody需要一个Collider!");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
ArcadeRigidbody.prototype.update = function () {
|
ArcadeRigidbody.prototype.update = function () {
|
||||||
var e_1, _a;
|
var e_1, _a;
|
||||||
@@ -2401,8 +2458,7 @@ var es;
|
|||||||
}
|
}
|
||||||
ProjectileMover.prototype.onAddedToEntity = function () {
|
ProjectileMover.prototype.onAddedToEntity = function () {
|
||||||
this._collider = this.entity.getComponent(es.Collider);
|
this._collider = this.entity.getComponent(es.Collider);
|
||||||
if (!this._collider)
|
es.Debug.warnIf(this._collider == null, "ProjectileMover没有Collider。ProjectilMover需要一个Collider!");
|
||||||
console.warn("ProjectileMover没有Collider。ProjectilMover需要一个Collider!");
|
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* 在考虑到碰撞的情况下移动实体
|
* 在考虑到碰撞的情况下移动实体
|
||||||
@@ -3133,8 +3189,7 @@ var es;
|
|||||||
ComponentList.prototype.remove = function (component) {
|
ComponentList.prototype.remove = function (component) {
|
||||||
var componentToRemove = new linq.List(this._componentsToRemove);
|
var componentToRemove = new linq.List(this._componentsToRemove);
|
||||||
var componentToAdd = new linq.List(this._componentsToAdd);
|
var componentToAdd = new linq.List(this._componentsToAdd);
|
||||||
if (componentToRemove.contains(component))
|
es.Debug.warnIf(componentToRemove.contains(component), "\u60A8\u6B63\u5728\u5C1D\u8BD5\u5220\u9664\u4E00\u4E2A\u60A8\u5DF2\u7ECF\u5220\u9664\u7684\u7EC4\u4EF6(" + component + ")");
|
||||||
console.warn("\u60A8\u6B63\u5728\u5C1D\u8BD5\u5220\u9664\u4E00\u4E2A\u60A8\u5DF2\u7ECF\u5220\u9664\u7684\u7EC4\u4EF6(" + component + ")");
|
|
||||||
// 这可能不是一个活动的组件,所以我们必须注意它是否还没有被处理,它可能正在同一帧中被删除
|
// 这可能不是一个活动的组件,所以我们必须注意它是否还没有被处理,它可能正在同一帧中被删除
|
||||||
if (componentToAdd.contains(component)) {
|
if (componentToAdd.contains(component)) {
|
||||||
componentToAdd.remove(component);
|
componentToAdd.remove(component);
|
||||||
@@ -3440,10 +3495,7 @@ var es;
|
|||||||
* @param entity
|
* @param entity
|
||||||
*/
|
*/
|
||||||
EntityList.prototype.remove = function (entity) {
|
EntityList.prototype.remove = function (entity) {
|
||||||
if (!this._entitiesToRemove.contains(entity)) {
|
es.Debug.warnIf(this._entitiesToRemove.contains(entity), "\u60A8\u6B63\u5728\u5C1D\u8BD5\u5220\u9664\u5DF2\u7ECF\u5220\u9664\u7684\u5B9E\u4F53(" + entity.name + ")");
|
||||||
console.warn("\u60A8\u6B63\u5728\u5C1D\u8BD5\u5220\u9664\u5DF2\u7ECF\u5220\u9664\u7684\u5B9E\u4F53(" + entity.name + ")");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 防止在同一帧中添加或删除实体
|
// 防止在同一帧中添加或删除实体
|
||||||
if (this._entitiesToAdded.contains(entity)) {
|
if (this._entitiesToAdded.contains(entity)) {
|
||||||
this._entitiesToAdded.remove(entity);
|
this._entitiesToAdded.remove(entity);
|
||||||
@@ -6384,9 +6436,8 @@ var es;
|
|||||||
for (var y = p1.y; y <= p2.y; y++) {
|
for (var y = p1.y; y <= p2.y; y++) {
|
||||||
// 单元格应该始终存在,因为这个碰撞器应该在所有查询的单元格中
|
// 单元格应该始终存在,因为这个碰撞器应该在所有查询的单元格中
|
||||||
var cell = this.cellAtPosition(x, y);
|
var cell = this.cellAtPosition(x, y);
|
||||||
if (!cell)
|
es.Insist.isNotNull(cell, "\u4ECE\u4E0D\u5B58\u5728\u78B0\u649E\u5668\u7684\u5355\u5143\u683C\u4E2D\u79FB\u9664\u78B0\u649E\u5668: [" + collider + "]");
|
||||||
console.log("\u4ECE\u4E0D\u5B58\u5728\u78B0\u649E\u5668\u7684\u5355\u5143\u683C\u4E2D\u79FB\u9664\u78B0\u649E\u5668: [" + collider + "]");
|
if (cell != null)
|
||||||
else
|
|
||||||
new linq.List(cell).remove(collider);
|
new linq.List(cell).remove(collider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7689,8 +7740,7 @@ var es;
|
|||||||
list = [];
|
list = [];
|
||||||
this._messageTable.set(eventType, list);
|
this._messageTable.set(eventType, list);
|
||||||
}
|
}
|
||||||
if (list.findIndex(function (funcPack) { return funcPack.func == handler; }) != -1)
|
es.Insist.isFalse(list.findIndex(function (funcPack) { return funcPack.func == handler; }) != -1, "您试图添加相同的观察者两次");
|
||||||
console.warn("您试图添加相同的观察者两次");
|
|
||||||
list.push(new FuncPack(handler, context));
|
list.push(new FuncPack(handler, context));
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
|||||||
2
source/bin/framework.min.js
vendored
2
source/bin/framework.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -81,10 +81,7 @@ module es {
|
|||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
public static set scene(value: Scene) {
|
public static set scene(value: Scene) {
|
||||||
if (!value) {
|
Insist.isNotNull(value, "场景不能为空");
|
||||||
console.error("场景不能为空");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._instance._scene == null) {
|
if (this._instance._scene == null) {
|
||||||
this._instance._scene = value;
|
this._instance._scene = value;
|
||||||
|
|||||||
46
source/src/Debug/Debug.ts
Normal file
46
source/src/Debug/Debug.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
module es {
|
||||||
|
export enum LogType {
|
||||||
|
error,
|
||||||
|
warn,
|
||||||
|
log,
|
||||||
|
info,
|
||||||
|
trace
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Debug {
|
||||||
|
public static warnIf(condition: boolean, format: string, ...args: any[]) {
|
||||||
|
if (condition)
|
||||||
|
this.log(LogType.warn, format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static warn(format: string, ...args: any[]) {
|
||||||
|
this.log(LogType.warn, format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static error(format: string, ...args: any[]) {
|
||||||
|
this.log(LogType.error, format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static log(type: LogType, format: string, ...args: any[]) {
|
||||||
|
switch(type) {
|
||||||
|
case LogType.error:
|
||||||
|
console.error(`${type}: ${StringUtils.format(format, args)}`);
|
||||||
|
break;
|
||||||
|
case LogType.warn:
|
||||||
|
console.warn(`${type}: ${StringUtils.format(format, args)}`);
|
||||||
|
break;
|
||||||
|
case LogType.log:
|
||||||
|
console.log(`${type}: ${StringUtils.format(format, args)}`);
|
||||||
|
break;
|
||||||
|
case LogType.info:
|
||||||
|
console.info(`${type}: ${StringUtils.format(format, args)}`);
|
||||||
|
break;
|
||||||
|
case LogType.trace:
|
||||||
|
console.trace(`${type}: ${StringUtils.format(format, args)}`);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('argument out of range');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ module es {
|
|||||||
* 我们在这里存储了各种系统的默认颜色,如对撞机调试渲染、Debug.drawText等。
|
* 我们在这里存储了各种系统的默认颜色,如对撞机调试渲染、Debug.drawText等。
|
||||||
* 命名方式尽可能采用CLASS-THING,以明确它的使用位置
|
* 命名方式尽可能采用CLASS-THING,以明确它的使用位置
|
||||||
*/
|
*/
|
||||||
export class Debug {
|
export class DebugDefault {
|
||||||
public static debugText: number = 0xffffff;
|
public static debugText: number = 0xffffff;
|
||||||
|
|
||||||
public static colliderBounds: number = 0xffffff * 0.3;
|
public static colliderBounds: number = 0xffffff * 0.3;
|
||||||
|
|||||||
@@ -129,9 +129,7 @@ module es {
|
|||||||
|
|
||||||
public onAddedToEntity(){
|
public onAddedToEntity(){
|
||||||
this._collider = this.entity.getComponent<es.Collider>(es.Collider);
|
this._collider = this.entity.getComponent<es.Collider>(es.Collider);
|
||||||
if (this._collider == null) {
|
Debug.warnIf(this._collider == null, "ArcadeRigidbody 没有 Collider。ArcadeRigidbody需要一个Collider!");
|
||||||
console.warn("ArcadeRigidbody 没有 Collider。ArcadeRigidbody需要一个Collider!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(){
|
public update(){
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ module es {
|
|||||||
|
|
||||||
public onAddedToEntity() {
|
public onAddedToEntity() {
|
||||||
this._collider = this.entity.getComponent<Collider>(Collider);
|
this._collider = this.entity.getComponent<Collider>(Collider);
|
||||||
if (!this._collider)
|
Debug.warnIf(this._collider == null, "ProjectileMover没有Collider。ProjectilMover需要一个Collider!");
|
||||||
console.warn("ProjectileMover没有Collider。ProjectilMover需要一个Collider!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -145,12 +145,9 @@ module es {
|
|||||||
* @param component
|
* @param component
|
||||||
*/
|
*/
|
||||||
public removeSceneComponent(component: SceneComponent) {
|
public removeSceneComponent(component: SceneComponent) {
|
||||||
if (!new linq.List(this._sceneComponents).contains(component)) {
|
const sceneComponentList = new linq.List(this._sceneComponents);
|
||||||
console.warn(`SceneComponent${component}不在SceneComponents列表中!`);
|
Insist.isTrue(sceneComponentList.contains(component), `SceneComponent${component}不在SceneComponents列表中!`);
|
||||||
return;
|
sceneComponentList.remove(component);
|
||||||
}
|
|
||||||
|
|
||||||
new linq.List(this._sceneComponents).remove(component);
|
|
||||||
component.onRemovedFromScene();
|
component.onRemovedFromScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,8 +52,7 @@ module es {
|
|||||||
public remove(component: Component) {
|
public remove(component: Component) {
|
||||||
let componentToRemove = new linq.List(this._componentsToRemove);
|
let componentToRemove = new linq.List(this._componentsToRemove);
|
||||||
let componentToAdd = new linq.List(this._componentsToAdd);
|
let componentToAdd = new linq.List(this._componentsToAdd);
|
||||||
if (componentToRemove.contains(component))
|
Debug.warnIf(componentToRemove.contains(component), `您正在尝试删除一个您已经删除的组件(${component})`);
|
||||||
console.warn(`您正在尝试删除一个您已经删除的组件(${component})`);
|
|
||||||
|
|
||||||
// 这可能不是一个活动的组件,所以我们必须注意它是否还没有被处理,它可能正在同一帧中被删除
|
// 这可能不是一个活动的组件,所以我们必须注意它是否还没有被处理,它可能正在同一帧中被删除
|
||||||
if (componentToAdd.contains(component)) {
|
if (componentToAdd.contains(component)) {
|
||||||
|
|||||||
@@ -56,10 +56,7 @@ module es {
|
|||||||
* @param entity
|
* @param entity
|
||||||
*/
|
*/
|
||||||
public remove(entity: Entity) {
|
public remove(entity: Entity) {
|
||||||
if (!this._entitiesToRemove.contains(entity)) {
|
Debug.warnIf(this._entitiesToRemove.contains(entity), `您正在尝试删除已经删除的实体(${entity.name})`);
|
||||||
console.warn(`您正在尝试删除已经删除的实体(${entity.name})`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 防止在同一帧中添加或删除实体
|
// 防止在同一帧中添加或删除实体
|
||||||
if (this._entitiesToAdded.contains(entity)) {
|
if (this._entitiesToAdded.contains(entity)) {
|
||||||
|
|||||||
@@ -75,9 +75,8 @@ module es {
|
|||||||
for (let y = p1.y; y <= p2.y; y++) {
|
for (let y = p1.y; y <= p2.y; y++) {
|
||||||
// 单元格应该始终存在,因为这个碰撞器应该在所有查询的单元格中
|
// 单元格应该始终存在,因为这个碰撞器应该在所有查询的单元格中
|
||||||
let cell = this.cellAtPosition(x, y);
|
let cell = this.cellAtPosition(x, y);
|
||||||
if (!cell)
|
Insist.isNotNull(cell, `从不存在碰撞器的单元格中移除碰撞器: [${collider}]`);
|
||||||
console.log(`从不存在碰撞器的单元格中移除碰撞器: [${collider}]`);
|
if (cell != null)
|
||||||
else
|
|
||||||
new linq.List(cell).remove(collider);
|
new linq.List(cell).remove(collider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,7 @@ module es {
|
|||||||
this._messageTable.set(eventType, list);
|
this._messageTable.set(eventType, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.findIndex(funcPack => funcPack.func == handler) != -1)
|
Insist.isFalse(list.findIndex(funcPack => funcPack.func == handler) != -1, "您试图添加相同的观察者两次");
|
||||||
console.warn("您试图添加相同的观察者两次");
|
|
||||||
list.push(new FuncPack(handler, context));
|
list.push(new FuncPack(handler, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user